@manuscripts/body-editor 3.12.67 → 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.
- package/dist/cjs/components/toolbar/type-selector/styles.js +2 -1
- package/dist/cjs/versions.js +1 -1
- package/dist/es/components/toolbar/type-selector/styles.js +2 -1
- package/dist/es/versions.js +1 -1
- package/dist/types/components/toolbar/type-selector/styles.d.ts +2 -2
- package/dist/types/lib/footnotes.d.ts +4 -2
- package/dist/types/lib/utils.d.ts +5 -4
- package/dist/types/versions.d.ts +1 -1
- package/package.json +37 -36
- package/{dist/es/lib/statistics.js → src/__mocks__/styleMock.ts} +2 -14
- package/src/assets.ts +20 -0
- package/src/classes/collabProvider.ts +38 -0
- package/src/clipboard.ts +54 -0
- package/src/commands.ts +2109 -0
- package/src/components/ChangeHandlingForm.tsx +54 -0
- package/src/components/LanguageDropdown/index.tsx +343 -0
- package/src/components/affiliations/AffiliationForm.tsx +238 -0
- package/src/components/affiliations/AffiliationItem.tsx +151 -0
- package/src/components/affiliations/AffiliationList.tsx +71 -0
- package/src/components/affiliations/AffiliationsModal.tsx +676 -0
- package/src/components/affiliations/AffiliationsPanel.tsx +76 -0
- package/src/components/affiliations/CreateAffiliationModal.tsx +135 -0
- package/src/components/authors/AuthorDetailsForm.tsx +438 -0
- package/src/components/authors/AuthorList.tsx +81 -0
- package/src/components/authors/AuthorsModal.tsx +642 -0
- package/src/components/authors/AuthorsPanel.tsx +69 -0
- package/src/components/authors/CreateAuthorModal.tsx +172 -0
- package/src/components/authors/CreditDrawer.tsx +71 -0
- package/src/components/authors/DraggableAuthor.tsx +228 -0
- package/src/components/authors/useManageAffiliations.tsx +77 -0
- package/src/components/authors/useManageCredit.tsx +63 -0
- package/src/components/authors-affiliations/AuthorsAndAffiliationsModals.tsx +170 -0
- package/src/components/authors-affiliations/GenericPanel.tsx +164 -0
- package/src/components/authors-affiliations/ModalTabs.tsx +100 -0
- package/src/components/awards/AwardForm.tsx +338 -0
- package/src/components/awards/AwardModal.tsx +120 -0
- package/src/components/awards/DeleteAwardDiaolog.tsx +52 -0
- package/src/components/dialog/ConfirmationDialog.tsx +131 -0
- package/src/components/form/CreateModalStyles.tsx +37 -0
- package/src/components/form/FormFooter.tsx +54 -0
- package/src/components/form/FormPlaceholder.tsx +71 -0
- package/src/components/form/ModalFormActions.tsx +88 -0
- package/src/components/form/UnsavedLabel.tsx +49 -0
- package/src/components/hooks/use-debounce.ts +56 -0
- package/src/components/hooks/useAffiliationShowsErrorIndicator.ts +51 -0
- package/src/components/hooks/useAuthorShowsErrorIndicator.ts +73 -0
- package/src/components/keyboard-shortcuts-modal/FormattedShortcut.tsx +56 -0
- package/src/components/keyboard-shortcuts-modal/KeyboardShortcutsModal.tsx +283 -0
- package/src/components/keyboard-shortcuts-modal/keyboard-shortcuts.ts +304 -0
- package/src/components/keywords/AddKeywordInline.tsx +284 -0
- package/src/components/keywords/DeleteKeywordDialog.tsx +52 -0
- package/src/components/modal-drawer/GenericDrawer.tsx +65 -0
- package/src/components/modal-drawer/GenericDrawerGroup.tsx +125 -0
- package/src/components/outline/DraggableTree.tsx +438 -0
- package/src/components/outline/ManuscriptOutline.tsx +127 -0
- package/src/components/outline/Outline.tsx +141 -0
- package/src/components/references/BibliographyItemSource.ts +80 -0
- package/src/components/references/CitationEditor.tsx +301 -0
- package/src/components/references/CitationViewer.tsx +62 -0
- package/src/components/references/ImportBibliographyForm.tsx +232 -0
- package/src/components/references/ImportBibliographyModal.tsx +159 -0
- package/src/components/references/ReferenceForm/PersonDropDown.tsx +93 -0
- package/src/components/references/ReferenceForm/ReferenceForm.tsx +701 -0
- package/src/components/references/ReferenceForm/config.ts +133 -0
- package/src/components/references/ReferenceForm/styled-components.ts +156 -0
- package/src/components/references/ReferenceLine.tsx +43 -0
- package/src/components/references/ReferenceSearch.tsx +163 -0
- package/src/components/references/ReferenceSearchResults.tsx +113 -0
- package/src/components/references/ReferenceSearchResultsPlaceholder.tsx +71 -0
- package/src/components/references/ReferenceSearchSection.tsx +124 -0
- package/src/components/references/ReferencesEditor.tsx +61 -0
- package/src/components/references/ReferencesModal.tsx +352 -0
- package/src/components/references/SearchInput.tsx +98 -0
- package/src/components/toolbar/InsertEmbedDialog.tsx +222 -0
- package/src/components/toolbar/InsertTableDialog.tsx +208 -0
- package/src/components/toolbar/ListMenuItem.tsx +203 -0
- package/src/components/toolbar/helpers.ts +547 -0
- package/src/components/toolbar/type-selector/OptionComponent.tsx +89 -0
- package/src/components/toolbar/type-selector/TypeSelector.tsx +157 -0
- package/src/components/toolbar/type-selector/styles.ts +79 -0
- package/src/components/views/CrossReferenceItems.tsx +199 -0
- package/src/components/views/DeleteEmbedDialog.tsx +83 -0
- package/src/components/views/DeleteFootnoteDialog.tsx +54 -0
- package/src/components/views/FigureDropdown.tsx +423 -0
- package/src/components/views/FootnotesSelector.tsx +255 -0
- package/src/components/views/InsertSpecialCharacter.tsx +245 -0
- package/src/components/views/LinkForm.tsx +220 -0
- package/src/components/views/TableCellContextMenu.tsx +241 -0
- package/src/configs/ManuscriptsEditor.ts +140 -0
- package/src/configs/editor-plugins.ts +119 -0
- package/src/configs/editor-views.ts +139 -0
- package/src/icons.ts +62 -0
- package/src/index.ts +65 -0
- package/src/keys/highlight.ts +65 -0
- package/src/keys/index.ts +33 -0
- package/src/keys/keyword.ts +69 -0
- package/src/keys/list.ts +156 -0
- package/src/keys/misc.ts +112 -0
- package/src/keys/title.ts +221 -0
- package/src/lib/__tests__/__fixtures__/doc.json +388 -0
- package/src/lib/__tests__/__snapshots__/paste.test.ts.snap +24 -0
- package/src/lib/__tests__/authors.test.ts +202 -0
- package/src/lib/__tests__/helpers.test.ts +46 -0
- package/src/lib/__tests__/paste.test.ts +57 -0
- package/src/lib/__tests__/plugins.test.ts +176 -0
- package/src/lib/__tests__/url.test.ts +31 -0
- package/src/lib/array-reducer.ts +68 -0
- package/src/lib/authors-and-affiliations.ts +81 -0
- package/src/lib/authors.ts +67 -0
- package/src/lib/capabilities.ts +55 -0
- package/src/lib/codemirror.ts +37 -0
- package/src/lib/comments.ts +123 -0
- package/src/lib/context-menu.ts +745 -0
- package/src/lib/copy.ts +30 -0
- package/src/lib/crossref.ts +90 -0
- package/src/lib/dnd.ts +29 -0
- package/src/lib/doc.ts +167 -0
- package/src/lib/dompurify.ts +28 -0
- package/src/lib/files.ts +180 -0
- package/src/lib/footnotes.ts +83 -0
- package/src/lib/get-media-type.ts +105 -0
- package/src/lib/helpers.ts +199 -0
- package/src/lib/hierarchy.ts +117 -0
- package/src/lib/languages.ts +37 -0
- package/src/lib/lists.ts +56 -0
- package/src/lib/math.ts +111 -0
- package/src/lib/media.ts +334 -0
- package/src/lib/navigation-utils.ts +235 -0
- package/src/lib/normalize.ts +70 -0
- package/src/lib/paste.ts +304 -0
- package/src/lib/placeholder.ts +32 -0
- package/src/lib/platform.ts +18 -0
- package/src/lib/plugins.ts +22 -0
- package/src/lib/popper.ts +180 -0
- package/src/lib/position-menu.ts +184 -0
- package/src/lib/references.ts +94 -0
- package/src/lib/template.ts +29 -0
- package/src/lib/track-changes-utils.ts +34 -0
- package/{dist/types/lib/statistics.d.ts → src/lib/url.ts} +11 -8
- package/src/lib/use-do-with-debounce.ts +39 -0
- package/src/lib/utils.ts +323 -0
- package/src/lib/view.ts +100 -0
- package/src/menus.tsx +684 -0
- package/src/node-type-icons.tsx +83 -0
- package/src/plugins/__tests__/__fixtures__/deleted-footnote.json +140 -0
- package/src/plugins/__tests__/__fixtures__/inserted-footnote.json +153 -0
- package/src/plugins/__tests__/footnotes.test.ts +67 -0
- package/src/plugins/accessibility_element.ts +219 -0
- package/src/plugins/add-subtitle.ts +102 -0
- package/src/plugins/affiliations.ts +136 -0
- package/src/plugins/alt-titles.ts +219 -0
- package/src/plugins/bibliography.ts +235 -0
- package/src/plugins/comments.ts +328 -0
- package/src/plugins/cross-references.ts +70 -0
- package/src/plugins/detect-inconsistency/detect-inconsistency-utils.ts +102 -0
- package/src/plugins/detect-inconsistency/index.ts +55 -0
- package/src/plugins/detect-inconsistency/validators.ts +283 -0
- package/src/plugins/doi.ts +66 -0
- package/src/plugins/editor-props.ts +39 -0
- package/src/plugins/elements.ts +60 -0
- package/src/plugins/footnotes.ts +298 -0
- package/src/plugins/link.ts +53 -0
- package/src/plugins/lock-body.ts +136 -0
- package/src/plugins/move-node.ts +55 -0
- package/src/plugins/objects.ts +125 -0
- package/src/plugins/paragraphs.ts +90 -0
- package/src/plugins/persist.ts +64 -0
- package/src/plugins/persistent-cursor.ts +66 -0
- package/src/plugins/placeholder.ts +219 -0
- package/src/plugins/prevent-empty.ts +50 -0
- package/src/plugins/search-replace/index.ts +157 -0
- package/src/plugins/search-replace/lib.ts +95 -0
- package/src/plugins/section_category.ts +212 -0
- package/src/plugins/section_title/autocompletion.ts +87 -0
- package/src/plugins/section_title/index.ts +105 -0
- package/src/plugins/selected-suggestion.ts +243 -0
- package/src/plugins/tables-cursor-fix.ts +143 -0
- package/src/plugins/translations.ts +263 -0
- package/src/rules.ts +60 -0
- package/src/selection.ts +112 -0
- package/src/testing/default-capabilities.ts +48 -0
- package/src/testing/default-editor-data.ts +73 -0
- package/src/testing/empty-editor-doc.json +62 -0
- package/src/testing/polyfill-dom.ts +43 -0
- package/src/testing/section-categories.json +161 -0
- package/src/testing/setup-editor.ts +55 -0
- package/src/tests.ts +42 -0
- package/src/toolbar.tsx +259 -0
- package/src/types/@citation-js/core.d.ts +16 -0
- package/src/types/@citation-js/index.d.ts +16 -0
- package/src/types/@citation-js/plugin-bibtex.d.ts +16 -0
- package/src/types/@citation-js/plugin-csl.d.ts +16 -0
- package/src/types/@citation-js/plugin-doi.d.ts +16 -0
- package/src/types/@citation-js/plugin-enw.d.ts +16 -0
- package/src/types/@citation-js/plugin-pubmed.d.ts +16 -0
- package/src/types/@citation-js/plugin-ris.d.ts +16 -0
- package/src/types/citeproc.d.ts +124 -0
- package/src/types/css.d.ts +16 -0
- package/src/types/json.d.ts +17 -0
- package/src/types/prosemirror-dev-tools.d.ts +16 -0
- package/src/types/prosemirror-dropcursor.d.ts +16 -0
- package/src/types/styled-components.d.ts +23 -0
- package/src/types.ts +49 -0
- package/src/useEditor.ts +244 -0
- package/src/versions.ts +3 -0
- package/src/views/ReactSubView.tsx +145 -0
- package/src/views/abstracts.ts +46 -0
- package/src/views/accessibility_element.ts +86 -0
- package/src/views/affiliations.ts +254 -0
- package/src/views/alt_title.ts +85 -0
- package/src/views/alt_titles_section.ts +97 -0
- package/src/views/attachment.ts +160 -0
- package/src/views/attachments.ts +72 -0
- package/src/views/author_notes.ts +96 -0
- package/src/views/award.ts +194 -0
- package/src/views/awards.ts +59 -0
- package/src/views/base_node_view.ts +85 -0
- package/src/views/bibliography_element.ts +313 -0
- package/src/views/block_view.ts +100 -0
- package/src/views/blockquote_element.ts +26 -0
- package/src/views/blockquote_element_editable.ts +24 -0
- package/src/views/box_element.ts +33 -0
- package/src/views/caption.ts +37 -0
- package/src/views/caption_title.ts +33 -0
- package/src/views/citation.ts +67 -0
- package/src/views/citation_editable.ts +312 -0
- package/src/views/contributors.ts +341 -0
- package/src/views/creators.ts +82 -0
- package/src/views/cross_reference.ts +74 -0
- package/src/views/cross_reference_editable.ts +113 -0
- package/src/views/editable_block.ts +141 -0
- package/src/views/embed.ts +345 -0
- package/src/views/empty.ts +26 -0
- package/src/views/equation.ts +47 -0
- package/src/views/equation_editable.ts +84 -0
- package/src/views/equation_element.ts +29 -0
- package/src/views/equation_element_editable.ts +21 -0
- package/src/views/figure.ts +84 -0
- package/src/views/figure_editable.ts +361 -0
- package/src/views/figure_element.ts +197 -0
- package/src/views/figure_element_editable.ts +21 -0
- package/src/views/footnote.ts +236 -0
- package/src/views/footnotes_element.ts +54 -0
- package/src/views/general_table_footnote.ts +140 -0
- package/src/views/hero_image.ts +76 -0
- package/src/views/hero_image_editable.ts +21 -0
- package/src/views/image_element.ts +373 -0
- package/src/views/image_element_editable.ts +21 -0
- package/src/views/inline_equation.ts +47 -0
- package/src/views/inline_equation_editable.ts +70 -0
- package/src/views/inline_footnote.ts +264 -0
- package/src/views/inline_footnote_editable.ts +20 -0
- package/src/views/keyword.ts +127 -0
- package/src/views/keyword_group.ts +109 -0
- package/src/views/link.ts +27 -0
- package/src/views/link_editable.ts +169 -0
- package/src/views/list.ts +46 -0
- package/src/views/list_item.ts +26 -0
- package/src/views/paragraph.ts +26 -0
- package/src/views/paragraph_editable.ts +21 -0
- package/src/views/placeholder.ts +35 -0
- package/src/views/placeholder_element.ts +38 -0
- package/src/views/placeholder_element_editable.ts +21 -0
- package/src/views/pullquote_element.ts +106 -0
- package/src/views/pullquote_element_editable.ts +24 -0
- package/src/views/quote_image_editable.ts +84 -0
- package/src/views/section.ts +64 -0
- package/src/views/section_label.ts +20 -0
- package/src/views/section_title.ts +87 -0
- package/src/views/section_title_editable.ts +21 -0
- package/src/views/subtitle.ts +42 -0
- package/src/views/subtitle_editable.ts +20 -0
- package/src/views/subtitles.ts +34 -0
- package/src/views/subtitles_editable.ts +21 -0
- package/src/views/supplement.ts +236 -0
- package/src/views/supplement_editable.ts +20 -0
- package/src/views/supplements.ts +65 -0
- package/src/views/supplements_editable.ts +21 -0
- package/src/views/table_cell.ts +150 -0
- package/src/views/table_element.ts +33 -0
- package/src/views/table_element_editable.ts +21 -0
- package/src/views/table_element_footer.ts +41 -0
- package/src/views/title.ts +46 -0
- package/src/views/title_editable.ts +20 -0
- package/src/views/trans_graphical_abstract.ts +55 -0
- package/src/views/trans_graphical_abstract_editable.ts +21 -0
- package/src/views/translated_abstract.ts +53 -0
- package/src/views/translated_abstract_editable.ts +21 -0
- package/dist/cjs/lib/statistics.js +0 -38
|
@@ -0,0 +1,438 @@
|
|
|
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
|
+
import {
|
|
17
|
+
TriangleCollapsedIcon,
|
|
18
|
+
TriangleExpandedIcon,
|
|
19
|
+
} from '@manuscripts/style-guide'
|
|
20
|
+
import {
|
|
21
|
+
isAttachmentsNode,
|
|
22
|
+
isBibliographySectionNode,
|
|
23
|
+
isSupplementsNode,
|
|
24
|
+
isElementNodeType,
|
|
25
|
+
isHeroImageNode,
|
|
26
|
+
ManuscriptEditorView,
|
|
27
|
+
ManuscriptNode,
|
|
28
|
+
ManuscriptNodeType,
|
|
29
|
+
nodeTitle,
|
|
30
|
+
nodeTitlePlaceholder,
|
|
31
|
+
schema,
|
|
32
|
+
} from '@manuscripts/transform'
|
|
33
|
+
import { Fragment } from 'prosemirror-model'
|
|
34
|
+
import React, { MouseEvent, useRef, useState } from 'react'
|
|
35
|
+
import { useDrag, useDrop } from 'react-dnd'
|
|
36
|
+
|
|
37
|
+
import { Capabilities } from '../../lib/capabilities'
|
|
38
|
+
import { ContextMenu } from '../../lib/context-menu'
|
|
39
|
+
import { DropSide, getDropSide } from '../../lib/dnd'
|
|
40
|
+
import { isBodyLocked } from '../../lib/utils'
|
|
41
|
+
import { nodeTypeIcon } from '../../node-type-icons'
|
|
42
|
+
import { PluginState, sectionTitleKey } from '../../plugins/section_title'
|
|
43
|
+
import { FileAttachment } from '../../lib/files'
|
|
44
|
+
import {
|
|
45
|
+
Outline,
|
|
46
|
+
OutlineItem,
|
|
47
|
+
OutlineItemArrow,
|
|
48
|
+
OutlineItemIcon,
|
|
49
|
+
OutlineItemLink,
|
|
50
|
+
OutlineItemLinkText,
|
|
51
|
+
OutlineItemNoArrow,
|
|
52
|
+
OutlineItemPlaceholder,
|
|
53
|
+
} from './Outline'
|
|
54
|
+
import { isDeleted } from '@manuscripts/track-changes-plugin'
|
|
55
|
+
|
|
56
|
+
const excludedTypes = [
|
|
57
|
+
schema.nodes.table,
|
|
58
|
+
schema.nodes.figure,
|
|
59
|
+
schema.nodes.footnotes_element,
|
|
60
|
+
schema.nodes.bibliography_element,
|
|
61
|
+
schema.nodes.keywords,
|
|
62
|
+
schema.nodes.affiliations,
|
|
63
|
+
schema.nodes.contributors,
|
|
64
|
+
schema.nodes.author_notes,
|
|
65
|
+
schema.nodes.title,
|
|
66
|
+
schema.nodes.alt_titles,
|
|
67
|
+
schema.nodes.alt_title,
|
|
68
|
+
schema.nodes.alt_text,
|
|
69
|
+
schema.nodes.long_desc,
|
|
70
|
+
schema.nodes.trans_abstract,
|
|
71
|
+
schema.nodes.trans_graphical_abstract,
|
|
72
|
+
schema.nodes.subtitles,
|
|
73
|
+
schema.nodes.subtitle,
|
|
74
|
+
schema.nodes.supplement,
|
|
75
|
+
]
|
|
76
|
+
|
|
77
|
+
const childrenExcludedTypes = [
|
|
78
|
+
schema.nodes.pullquote_element,
|
|
79
|
+
schema.nodes.blockquote_element,
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
export interface TreeItem {
|
|
83
|
+
index: number
|
|
84
|
+
items: TreeItem[]
|
|
85
|
+
node: ManuscriptNode
|
|
86
|
+
pos: number
|
|
87
|
+
endPos: number
|
|
88
|
+
parent?: ManuscriptNode
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const isExcluded = (nodeType: ManuscriptNodeType) => {
|
|
92
|
+
return excludedTypes.includes(nodeType)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const isChildrenExcluded = (nodeType: ManuscriptNodeType) => {
|
|
96
|
+
return childrenExcludedTypes.includes(nodeType)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
interface TreeBuilderOptions {
|
|
100
|
+
node: ManuscriptNode
|
|
101
|
+
pos: number
|
|
102
|
+
index: number
|
|
103
|
+
parent?: ManuscriptNode
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
type TreeBuilder = (options: TreeBuilderOptions) => TreeItem
|
|
107
|
+
|
|
108
|
+
const isAbstractOrBackmatter = (item: TreeItem) => {
|
|
109
|
+
return (
|
|
110
|
+
item.parent &&
|
|
111
|
+
(item.parent.type === schema.nodes.abstracts ||
|
|
112
|
+
item.parent.type === schema.nodes.backmatter)
|
|
113
|
+
)
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const isManuscriptNode = (node: ManuscriptNode | undefined) => {
|
|
117
|
+
return node?.type === schema.nodes.manuscript
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
type EditorPropsWithFiles = ManuscriptEditorView['props'] & {
|
|
121
|
+
getFiles?: () => FileAttachment[]
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const isPdfFile = (file?: FileAttachment) => {
|
|
125
|
+
if (!file?.name) {
|
|
126
|
+
return false
|
|
127
|
+
}
|
|
128
|
+
const name = file.name.toLowerCase()
|
|
129
|
+
return name.endsWith('.pdf')
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const getEditorFiles = (view?: ManuscriptEditorView) => {
|
|
133
|
+
const props = view?.props as EditorPropsWithFiles | undefined
|
|
134
|
+
return props?.getFiles?.()
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export const buildTree: TreeBuilder = ({
|
|
138
|
+
node,
|
|
139
|
+
pos,
|
|
140
|
+
index,
|
|
141
|
+
parent,
|
|
142
|
+
}): TreeItem => {
|
|
143
|
+
const items: TreeItem[] = []
|
|
144
|
+
const startPos = pos + 1 // TODO: don't increment this?
|
|
145
|
+
const endPos = pos + node.nodeSize
|
|
146
|
+
|
|
147
|
+
if (!isChildrenExcluded(node.type)) {
|
|
148
|
+
node.forEach((childNode, offset, childIndex) => {
|
|
149
|
+
if (isExcluded(childNode.type)) {
|
|
150
|
+
return
|
|
151
|
+
}
|
|
152
|
+
if (
|
|
153
|
+
isManuscriptNode(node) ||
|
|
154
|
+
((!childNode.isAtom || isElementNodeType(childNode.type)) &&
|
|
155
|
+
childNode.attrs.id &&
|
|
156
|
+
!isDeleted(childNode))
|
|
157
|
+
) {
|
|
158
|
+
items.push(
|
|
159
|
+
buildTree({
|
|
160
|
+
node: childNode,
|
|
161
|
+
pos: startPos + offset,
|
|
162
|
+
index: childIndex,
|
|
163
|
+
parent: node,
|
|
164
|
+
})
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return { node, index, items, pos, endPos, parent }
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface DraggableTreeProps {
|
|
174
|
+
depth: number
|
|
175
|
+
tree: TreeItem
|
|
176
|
+
view?: ManuscriptEditorView
|
|
177
|
+
can?: Capabilities
|
|
178
|
+
getFiles?: () => FileAttachment[]
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
export const DraggableTree: React.FC<DraggableTreeProps> = ({
|
|
182
|
+
tree,
|
|
183
|
+
view,
|
|
184
|
+
depth,
|
|
185
|
+
can,
|
|
186
|
+
getFiles,
|
|
187
|
+
}) => {
|
|
188
|
+
const [dropSide, setDropSide] = useState<DropSide>()
|
|
189
|
+
const [isOpen, setOpen] = useState(depth === 0)
|
|
190
|
+
const ref = useRef<HTMLDivElement>(null)
|
|
191
|
+
// Disable drag-and-drop functionality when the body is locked
|
|
192
|
+
const disableDragAndDrop = view
|
|
193
|
+
? isBodyLocked(view.state) || !can?.editArticle
|
|
194
|
+
: true
|
|
195
|
+
|
|
196
|
+
const { node, items, parent } = tree
|
|
197
|
+
const sectionTitleState: PluginState | undefined = view
|
|
198
|
+
? sectionTitleKey.getState(view.state)
|
|
199
|
+
: undefined
|
|
200
|
+
|
|
201
|
+
const itemText = (node: ManuscriptNode) => {
|
|
202
|
+
const text = nodeTitle(node)
|
|
203
|
+
let sectionNumber =
|
|
204
|
+
node.type.name === 'section' && sectionTitleState
|
|
205
|
+
? (sectionTitleState.get(node.attrs.id) ?? '')
|
|
206
|
+
: ''
|
|
207
|
+
sectionNumber = sectionNumber ? `${sectionNumber}.` : ''
|
|
208
|
+
|
|
209
|
+
if (text) {
|
|
210
|
+
return `${sectionNumber}${sectionNumber ? ' ' : ''}${text.trim()}`
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
const placeholder = nodeTitlePlaceholder(node.type)
|
|
214
|
+
|
|
215
|
+
return (
|
|
216
|
+
<OutlineItemPlaceholder>
|
|
217
|
+
{sectionNumber && `${sectionNumber} `}
|
|
218
|
+
{placeholder}
|
|
219
|
+
</OutlineItemPlaceholder>
|
|
220
|
+
)
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
const toggleOpen = () => {
|
|
224
|
+
setOpen(!isOpen)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const [{ isDragging }, dragRef] = useDrag({
|
|
228
|
+
type: 'outline',
|
|
229
|
+
item: tree,
|
|
230
|
+
canDrag: () => {
|
|
231
|
+
// Prevent dragging if the node is deleted, the body is locked, or editing is not allowed
|
|
232
|
+
return depth !== 0 && !disableDragAndDrop && !isDeleted(node)
|
|
233
|
+
},
|
|
234
|
+
collect: (monitor) => ({
|
|
235
|
+
isDragging: monitor.isDragging(),
|
|
236
|
+
}),
|
|
237
|
+
})
|
|
238
|
+
|
|
239
|
+
const [{ isOver }, dropRef] = useDrop({
|
|
240
|
+
accept: 'outline',
|
|
241
|
+
canDrop(item: TreeItem, monitor) {
|
|
242
|
+
if (disableDragAndDrop) {
|
|
243
|
+
return false
|
|
244
|
+
}
|
|
245
|
+
if (isAbstractOrBackmatter(item) || isAbstractOrBackmatter(tree)) {
|
|
246
|
+
return false
|
|
247
|
+
}
|
|
248
|
+
if (!ref.current) {
|
|
249
|
+
return false
|
|
250
|
+
}
|
|
251
|
+
if (!tree.parent) {
|
|
252
|
+
return false
|
|
253
|
+
}
|
|
254
|
+
// can't drop on itself
|
|
255
|
+
if (item.node.attrs.id === tree.node.attrs.id) {
|
|
256
|
+
return false
|
|
257
|
+
}
|
|
258
|
+
// can't drop within itself
|
|
259
|
+
if (item.pos <= tree.pos && item.endPos >= tree.endPos) {
|
|
260
|
+
return false
|
|
261
|
+
}
|
|
262
|
+
// can't drop immediately before/after itself
|
|
263
|
+
if (tree.pos === item.endPos || item.pos === tree.endPos) {
|
|
264
|
+
return false
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
const side = getDropSide(ref.current, monitor)
|
|
268
|
+
const index = side === 'before' ? tree.index : tree.index + 1
|
|
269
|
+
|
|
270
|
+
return tree.parent.canReplace(index, index, Fragment.from(item.node))
|
|
271
|
+
},
|
|
272
|
+
hover(item, monitor) {
|
|
273
|
+
if (disableDragAndDrop || !ref.current || !monitor.canDrop()) {
|
|
274
|
+
return
|
|
275
|
+
}
|
|
276
|
+
const side = getDropSide(ref.current, monitor)
|
|
277
|
+
setDropSide(side)
|
|
278
|
+
},
|
|
279
|
+
drop(item: TreeItem, monitor) {
|
|
280
|
+
if (disableDragAndDrop || !ref.current || !view) {
|
|
281
|
+
return
|
|
282
|
+
}
|
|
283
|
+
const side = getDropSide(ref.current, monitor)
|
|
284
|
+
const pos = side === 'before' ? tree.pos - 1 : tree.endPos - 1
|
|
285
|
+
let sourcePos = item.pos - 1
|
|
286
|
+
|
|
287
|
+
const node = item.node.type.schema.nodes[item.node.type.name].create(
|
|
288
|
+
{
|
|
289
|
+
...item.node.attrs,
|
|
290
|
+
},
|
|
291
|
+
item.node.content
|
|
292
|
+
)
|
|
293
|
+
|
|
294
|
+
const tr = view.state.tr.insert(pos, node)
|
|
295
|
+
sourcePos = tr.mapping.map(sourcePos)
|
|
296
|
+
tr.delete(sourcePos, sourcePos + item.node.nodeSize)
|
|
297
|
+
view.dispatch(tr)
|
|
298
|
+
},
|
|
299
|
+
collect: (monitor) => ({
|
|
300
|
+
isOver: monitor.isOver({ shallow: true }),
|
|
301
|
+
}),
|
|
302
|
+
})
|
|
303
|
+
|
|
304
|
+
const isDeletedItem = isDeleted(node)
|
|
305
|
+
const isHeroImage = isHeroImageNode(node)
|
|
306
|
+
const isSupplements = isSupplementsNode(node)
|
|
307
|
+
const isMainDocument = isAttachmentsNode(node)
|
|
308
|
+
const editorFiles = isMainDocument
|
|
309
|
+
? (getFiles?.() ?? getEditorFiles(view))
|
|
310
|
+
: undefined
|
|
311
|
+
|
|
312
|
+
const isTop =
|
|
313
|
+
isManuscriptNode(parent) &&
|
|
314
|
+
!isHeroImage &&
|
|
315
|
+
!isSupplements &&
|
|
316
|
+
!isMainDocument
|
|
317
|
+
|
|
318
|
+
// Hide attachments node from outline when it's empty
|
|
319
|
+
if (isMainDocument && node.childCount === 0) {
|
|
320
|
+
return null
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
if (isMainDocument) {
|
|
324
|
+
const attachmentIds = new Set<string>()
|
|
325
|
+
node.forEach((childNode) => {
|
|
326
|
+
const href = childNode.attrs?.href
|
|
327
|
+
if (href) {
|
|
328
|
+
attachmentIds.add(href.replace(/^attachment:/, ''))
|
|
329
|
+
}
|
|
330
|
+
})
|
|
331
|
+
|
|
332
|
+
const mainDocumentFile =
|
|
333
|
+
editorFiles?.find((file) => {
|
|
334
|
+
const fileId = file.id?.replace(/^attachment:/, '')
|
|
335
|
+
return !!fileId && attachmentIds.has(fileId)
|
|
336
|
+
}) ?? editorFiles?.find((file) => isPdfFile(file))
|
|
337
|
+
const isMainDocumentPDF = isPdfFile(mainDocumentFile)
|
|
338
|
+
|
|
339
|
+
// Hide main document in outline if it is not a PDF
|
|
340
|
+
if (!isMainDocumentPDF) {
|
|
341
|
+
return null
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
const handleContextMenu = (e: MouseEvent) => {
|
|
346
|
+
e.preventDefault()
|
|
347
|
+
e.stopPropagation()
|
|
348
|
+
|
|
349
|
+
if (!can?.editArticle) {
|
|
350
|
+
return false
|
|
351
|
+
}
|
|
352
|
+
if (!view) {
|
|
353
|
+
return null
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const menu = new ContextMenu(tree.node, view, () => tree.pos - 1)
|
|
357
|
+
menu.showEditMenu(e.currentTarget as HTMLAnchorElement)
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
const handleKeyDown = (e: React.KeyboardEvent<HTMLDivElement>) => {
|
|
361
|
+
if (e.key === 'Enter') {
|
|
362
|
+
e.preventDefault()
|
|
363
|
+
e.stopPropagation()
|
|
364
|
+
|
|
365
|
+
if (items.length > 0) {
|
|
366
|
+
// Has children: expand/collapse
|
|
367
|
+
toggleOpen()
|
|
368
|
+
} else {
|
|
369
|
+
// No children: navigate to the link
|
|
370
|
+
const link = (e.currentTarget as HTMLElement).querySelector('a')
|
|
371
|
+
if (link) {
|
|
372
|
+
link.click()
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
dragRef(dropRef(ref))
|
|
379
|
+
|
|
380
|
+
const classNames = [
|
|
381
|
+
isDragging && 'dragging',
|
|
382
|
+
isOver && dropSide && `drop-${dropSide}`,
|
|
383
|
+
isDeletedItem && 'deleted',
|
|
384
|
+
isHeroImage && 'hero-image',
|
|
385
|
+
isSupplements && 'supplements',
|
|
386
|
+
isBibliographySectionNode(node) && 'references',
|
|
387
|
+
isMainDocument && 'main-document',
|
|
388
|
+
]
|
|
389
|
+
.filter(Boolean)
|
|
390
|
+
.join(' ') // .filter(Boolean) removes all falsy values (false, '', null, etc.)
|
|
391
|
+
return (
|
|
392
|
+
<Outline ref={ref} className={classNames}>
|
|
393
|
+
{!isTop && node.type.name != 'manuscript' && (
|
|
394
|
+
<OutlineItem
|
|
395
|
+
depth={isHeroImage || isSupplements || isMainDocument ? 1 : depth}
|
|
396
|
+
onContextMenu={handleContextMenu}
|
|
397
|
+
onKeyDown={handleKeyDown}
|
|
398
|
+
tabIndex={-1}
|
|
399
|
+
data-outline-item
|
|
400
|
+
>
|
|
401
|
+
{items.length ? (
|
|
402
|
+
<OutlineItemArrow
|
|
403
|
+
aria-label={`${isOpen ? 'Collapse' : 'Expand'} ${node.type.name}`}
|
|
404
|
+
onClick={toggleOpen}
|
|
405
|
+
tabIndex={-1}
|
|
406
|
+
>
|
|
407
|
+
{isOpen ? <TriangleExpandedIcon /> : <TriangleCollapsedIcon />}
|
|
408
|
+
</OutlineItemArrow>
|
|
409
|
+
) : (
|
|
410
|
+
<OutlineItemNoArrow />
|
|
411
|
+
)}
|
|
412
|
+
|
|
413
|
+
<OutlineItemLink to={`#${node.attrs.id}`} tabIndex={-1}>
|
|
414
|
+
<OutlineItemIcon>{nodeTypeIcon(node.type)}</OutlineItemIcon>
|
|
415
|
+
<OutlineItemLinkText className={`outline-text-${node.type.name}`}>
|
|
416
|
+
{itemText(node)}
|
|
417
|
+
</OutlineItemLinkText>
|
|
418
|
+
</OutlineItemLink>
|
|
419
|
+
</OutlineItem>
|
|
420
|
+
)}
|
|
421
|
+
|
|
422
|
+
{items.length ? (
|
|
423
|
+
<div className={`subtree ${isOpen ? '' : 'collapsed'}`}>
|
|
424
|
+
{items.map((subtree, index) => (
|
|
425
|
+
<DraggableTree
|
|
426
|
+
key={subtree.node.attrs.id || 'subtree-' + index}
|
|
427
|
+
tree={subtree}
|
|
428
|
+
view={view}
|
|
429
|
+
depth={!tree.parent ? depth : depth + 1}
|
|
430
|
+
can={can}
|
|
431
|
+
getFiles={getFiles}
|
|
432
|
+
/>
|
|
433
|
+
))}
|
|
434
|
+
</div>
|
|
435
|
+
) : null}
|
|
436
|
+
</Outline>
|
|
437
|
+
)
|
|
438
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
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 { ManuscriptEditorView, ManuscriptNode } from '@manuscripts/transform'
|
|
18
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
|
19
|
+
|
|
20
|
+
import { Capabilities } from '../../lib/capabilities'
|
|
21
|
+
import { FileAttachment } from '../../lib/files'
|
|
22
|
+
import { useDebounce } from '../hooks/use-debounce'
|
|
23
|
+
import { buildTree, DraggableTree, TreeItem } from './DraggableTree'
|
|
24
|
+
|
|
25
|
+
export interface ManuscriptOutlineProps {
|
|
26
|
+
doc: ManuscriptNode | null
|
|
27
|
+
can?: Capabilities
|
|
28
|
+
view?: ManuscriptEditorView
|
|
29
|
+
getFiles?: () => FileAttachment[]
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export const ManuscriptOutline: React.FC<ManuscriptOutlineProps> = (props) => {
|
|
33
|
+
const [values, setValues] = useState<{
|
|
34
|
+
tree: TreeItem
|
|
35
|
+
view?: ManuscriptEditorView
|
|
36
|
+
can?: Capabilities
|
|
37
|
+
getFiles?: () => FileAttachment[]
|
|
38
|
+
}>()
|
|
39
|
+
const containerRef = useRef<HTMLDivElement>(null)
|
|
40
|
+
|
|
41
|
+
const debouncedProps = useDebounce(props, 500)
|
|
42
|
+
|
|
43
|
+
useEffect(() => {
|
|
44
|
+
const { doc, view } = debouncedProps
|
|
45
|
+
|
|
46
|
+
if (doc) {
|
|
47
|
+
const tree = buildTree({
|
|
48
|
+
node: doc,
|
|
49
|
+
pos: 0,
|
|
50
|
+
index: 0,
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
setValues({ tree, view, can: props.can, getFiles: props.getFiles })
|
|
54
|
+
} else {
|
|
55
|
+
setValues(undefined)
|
|
56
|
+
}
|
|
57
|
+
}, [debouncedProps, props.can, props.getFiles])
|
|
58
|
+
|
|
59
|
+
// Get all visible outline items (excluding those in collapsed subtrees)
|
|
60
|
+
const getOutlineItems = useCallback(() => {
|
|
61
|
+
if (!containerRef.current) return []
|
|
62
|
+
const allItems = Array.from(
|
|
63
|
+
containerRef.current.querySelectorAll<HTMLElement>('[data-outline-item]')
|
|
64
|
+
)
|
|
65
|
+
|
|
66
|
+
// Filter out items that are inside a collapsed subtree
|
|
67
|
+
return allItems.filter((item) => {
|
|
68
|
+
let parent = item.parentElement
|
|
69
|
+
while (parent && parent !== containerRef.current) {
|
|
70
|
+
if (
|
|
71
|
+
parent.classList.contains('subtree') &&
|
|
72
|
+
parent.classList.contains('collapsed')
|
|
73
|
+
) {
|
|
74
|
+
return false
|
|
75
|
+
}
|
|
76
|
+
parent = parent.parentElement
|
|
77
|
+
}
|
|
78
|
+
return true
|
|
79
|
+
})
|
|
80
|
+
}, [])
|
|
81
|
+
|
|
82
|
+
// Set roving tabindex: only first item is tabbable
|
|
83
|
+
useEffect(() => {
|
|
84
|
+
const items = getOutlineItems()
|
|
85
|
+
items.forEach((item, index) => {
|
|
86
|
+
item.tabIndex = index === 0 ? 0 : -1
|
|
87
|
+
})
|
|
88
|
+
}, [getOutlineItems, values])
|
|
89
|
+
|
|
90
|
+
const handleKeyDown = useCallback(
|
|
91
|
+
(event: React.KeyboardEvent<HTMLDivElement>) => {
|
|
92
|
+
if (event.key !== 'ArrowDown' && event.key !== 'ArrowUp') {
|
|
93
|
+
return
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const target = event.target as HTMLElement
|
|
97
|
+
// Only handle if an outline item is focused
|
|
98
|
+
if (!target.hasAttribute('data-outline-item')) {
|
|
99
|
+
return
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const items = getOutlineItems()
|
|
103
|
+
const currentIndex = items.indexOf(target)
|
|
104
|
+
|
|
105
|
+
if (currentIndex === -1) return
|
|
106
|
+
|
|
107
|
+
event.preventDefault()
|
|
108
|
+
|
|
109
|
+
let nextIndex: number
|
|
110
|
+
if (event.key === 'ArrowDown') {
|
|
111
|
+
nextIndex = (currentIndex + 1) % items.length
|
|
112
|
+
} else {
|
|
113
|
+
nextIndex = (currentIndex - 1 + items.length) % items.length
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const nextItem = items[nextIndex]
|
|
117
|
+
nextItem?.focus()
|
|
118
|
+
},
|
|
119
|
+
[getOutlineItems]
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
return values && values.view ? (
|
|
123
|
+
<div ref={containerRef} onKeyDown={handleKeyDown}>
|
|
124
|
+
<DraggableTree {...values} depth={0} />
|
|
125
|
+
</div>
|
|
126
|
+
) : null
|
|
127
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
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 { Link } from 'react-router-dom'
|
|
18
|
+
import styled from 'styled-components'
|
|
19
|
+
|
|
20
|
+
export const OutlineItemIcon = styled.span`
|
|
21
|
+
display: inline-flex;
|
|
22
|
+
width: 1.2em;
|
|
23
|
+
height: 1.3em;
|
|
24
|
+
justify-content: center;
|
|
25
|
+
align-items: center;
|
|
26
|
+
padding: 2px;
|
|
27
|
+
flex-shrink: 0;
|
|
28
|
+
`
|
|
29
|
+
|
|
30
|
+
export const OutlineItem = styled.div<{
|
|
31
|
+
depth: number
|
|
32
|
+
}>`
|
|
33
|
+
align-items: center;
|
|
34
|
+
color: ${(props) => props.theme.colors.text.primary};
|
|
35
|
+
box-sizing: border-box;
|
|
36
|
+
cursor: pointer;
|
|
37
|
+
display: flex;
|
|
38
|
+
font-size: ${(props) =>
|
|
39
|
+
props.depth === 0
|
|
40
|
+
? props.theme.font.size.large
|
|
41
|
+
: props.theme.font.size.medium};
|
|
42
|
+
line-height: 30px;
|
|
43
|
+
margin-left: -${(props) => props.theme.grid.unit * 10}px;
|
|
44
|
+
margin-right: -${(props) => props.theme.grid.unit * 5}px;
|
|
45
|
+
overflow-x: hidden;
|
|
46
|
+
padding-right: ${(props) => props.theme.grid.unit * 5}px;
|
|
47
|
+
padding-left: ${(props) => 20 + props.depth * 20}px;
|
|
48
|
+
white-space: nowrap;
|
|
49
|
+
|
|
50
|
+
&:hover {
|
|
51
|
+
background: ${(props) => props.theme.colors.background.fifth};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
&:focus-visible {
|
|
55
|
+
background: ${(props) => props.theme.colors.background.fifth};
|
|
56
|
+
outline: 2px solid #bce7f6;
|
|
57
|
+
outline-offset: -2px;
|
|
58
|
+
}
|
|
59
|
+
`
|
|
60
|
+
|
|
61
|
+
export const OutlineItemArrow = styled.button`
|
|
62
|
+
display: inline-block;
|
|
63
|
+
cursor: pointer;
|
|
64
|
+
border: none;
|
|
65
|
+
background: transparent;
|
|
66
|
+
padding: 0 ${(props) => props.theme.grid.unit}px;
|
|
67
|
+
flex-shrink: 0;
|
|
68
|
+
font-size: ${(props) => props.theme.font.size.normal};
|
|
69
|
+
|
|
70
|
+
&:hover use {
|
|
71
|
+
fill: #ccc;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
&:focus {
|
|
75
|
+
outline: none;
|
|
76
|
+
}
|
|
77
|
+
`
|
|
78
|
+
|
|
79
|
+
export const OutlineItemNoArrow = styled.span`
|
|
80
|
+
display: inline-block;
|
|
81
|
+
width: 25px;
|
|
82
|
+
flex-shrink: 0;
|
|
83
|
+
`
|
|
84
|
+
|
|
85
|
+
export const OutlineItemLink = styled(Link)`
|
|
86
|
+
flex: 1;
|
|
87
|
+
display: inline-flex;
|
|
88
|
+
align-items: center;
|
|
89
|
+
overflow-x: hidden;
|
|
90
|
+
color: inherit;
|
|
91
|
+
text-decoration: none;
|
|
92
|
+
height: 100%;
|
|
93
|
+
border-bottom: 1px solid transparent;
|
|
94
|
+
border-top: 1px solid transparent;
|
|
95
|
+
|
|
96
|
+
&:focus,
|
|
97
|
+
&:active {
|
|
98
|
+
outline: none;
|
|
99
|
+
}
|
|
100
|
+
`
|
|
101
|
+
|
|
102
|
+
export const OutlineItemLinkText = styled.span`
|
|
103
|
+
flex: 1;
|
|
104
|
+
display: inline-block;
|
|
105
|
+
overflow-x: hidden;
|
|
106
|
+
text-overflow: ellipsis;
|
|
107
|
+
margin-left: ${(props) => props.theme.grid.unit * 2}px;
|
|
108
|
+
`
|
|
109
|
+
|
|
110
|
+
export const Outline = styled.div`
|
|
111
|
+
font-size: ${(props) => props.theme.font.size.medium};
|
|
112
|
+
position: relative;
|
|
113
|
+
|
|
114
|
+
& .outline-text-title {
|
|
115
|
+
font-size: ${(props) => props.theme.font.size.large};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
&.dragging {
|
|
119
|
+
opacity: 0.5;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
&.drop-before > ${OutlineItem} > ${OutlineItemLink} {
|
|
123
|
+
border-top-color: ${(props) => props.theme.colors.brand.dark};
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
&.drop-after > ${OutlineItem} > ${OutlineItemLink} {
|
|
127
|
+
border-bottom-color: ${(props) => props.theme.colors.brand.dark};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
& .subtree.collapsed {
|
|
131
|
+
display: none;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
& div:has(.supplements, .hero-image, .main-document) .references {
|
|
135
|
+
margin-bottom: 5px;
|
|
136
|
+
padding-bottom: 5px;
|
|
137
|
+
border-bottom: 1px dashed #ddd;
|
|
138
|
+
}
|
|
139
|
+
`
|
|
140
|
+
|
|
141
|
+
export const OutlineItemPlaceholder = styled.span``
|