@manuscripts/body-editor 1.7.3 → 1.7.5

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 (43) hide show
  1. package/dist/cjs/assets.js +25 -1
  2. package/dist/cjs/configs/editor-plugins.js +2 -4
  3. package/dist/cjs/index.js +3 -1
  4. package/dist/cjs/lib/track-changes-utils.js +13 -4
  5. package/dist/cjs/plugins/comment_annotation.js +2 -1
  6. package/dist/cjs/plugins/highlight/findHighlightMarkers.js +1 -7
  7. package/dist/cjs/plugins/selected-suggestion-ui.js +129 -0
  8. package/dist/cjs/views/affiliation.js +2 -1
  9. package/dist/cjs/views/bibliography_element.js +23 -6
  10. package/dist/cjs/views/citation.js +4 -1
  11. package/dist/cjs/views/contributors.js +14 -3
  12. package/dist/cjs/views/cross_reference.js +4 -1
  13. package/dist/cjs/views/keyword.js +17 -7
  14. package/dist/es/assets.js +24 -0
  15. package/dist/es/configs/editor-plugins.js +2 -4
  16. package/dist/es/index.js +1 -0
  17. package/dist/es/lib/track-changes-utils.js +11 -3
  18. package/dist/es/plugins/comment_annotation.js +2 -1
  19. package/dist/es/plugins/highlight/findHighlightMarkers.js +2 -8
  20. package/dist/es/plugins/selected-suggestion-ui.js +126 -0
  21. package/dist/es/views/affiliation.js +2 -1
  22. package/dist/es/views/bibliography_element.js +22 -5
  23. package/dist/es/views/citation.js +4 -1
  24. package/dist/es/views/contributors.js +14 -3
  25. package/dist/es/views/cross_reference.js +4 -1
  26. package/dist/es/views/keyword.js +17 -7
  27. package/dist/types/assets.d.ts +1 -0
  28. package/dist/types/configs/editor-plugins.d.ts +1 -1
  29. package/dist/types/index.d.ts +1 -0
  30. package/dist/types/lib/track-changes-utils.d.ts +3 -1
  31. package/dist/types/plugins/{track-changes-ui.d.ts → selected-suggestion-ui.d.ts} +7 -5
  32. package/dist/types/views/affiliation.d.ts +0 -1
  33. package/dist/types/views/base_node_view.d.ts +1 -0
  34. package/dist/types/views/bibliography_element.d.ts +1 -0
  35. package/dist/types/views/contributors.d.ts +1 -1
  36. package/package.json +1 -1
  37. package/styles/AdvancedEditor.css +18 -3
  38. package/styles/Editor.css +2 -2
  39. package/dist/cjs/plugins/track-changes-ui.js +0 -104
  40. package/dist/cjs/plugins/tracking-mark.js +0 -123
  41. package/dist/es/plugins/track-changes-ui.js +0 -102
  42. package/dist/es/plugins/tracking-mark.js +0 -118
  43. package/dist/types/plugins/tracking-mark.d.ts +0 -7
@@ -0,0 +1,126 @@
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 { trackChangesPluginKey } from '@manuscripts/track-changes-plugin';
17
+ import { isEqual } from 'lodash';
18
+ import { Plugin, PluginKey } from 'prosemirror-state';
19
+ import { Decoration, DecorationSet } from 'prosemirror-view';
20
+ class SuggestionView {
21
+ constructor(view) {
22
+ this.listener = (e) => {
23
+ const changeId = e.currentTarget.getAttribute('data-track-id');
24
+ this.view.dispatch(this.view.state.tr.setMeta(SET_SUGGESTION_ID, changeId));
25
+ };
26
+ this.view = view;
27
+ this.addEventListener(view);
28
+ this.update(view, undefined);
29
+ }
30
+ update(view, prevState) {
31
+ var _a, _b;
32
+ this.view = view;
33
+ if (!prevState) {
34
+ return;
35
+ }
36
+ const oldChanges = ((_a = trackChangesPluginKey.getState(prevState)) === null || _a === void 0 ? void 0 : _a.changeSet.changes) || [];
37
+ const newChangeSet = (_b = trackChangesPluginKey.getState(view.state)) === null || _b === void 0 ? void 0 : _b.changeSet;
38
+ if (newChangeSet && !isEqual(oldChanges, newChangeSet.changes)) {
39
+ this.addEventListener(view);
40
+ oldChanges.map((change) => {
41
+ var _a;
42
+ if (!newChangeSet.get(change.id) ||
43
+ ((_a = newChangeSet.get(change.id)) === null || _a === void 0 ? void 0 : _a.dataTracked.status) === 'rejected') {
44
+ const dom = view.dom.querySelector(`[data-track-id="${change.id}"]`);
45
+ dom === null || dom === void 0 ? void 0 : dom.removeEventListener('click', this.listener);
46
+ }
47
+ });
48
+ }
49
+ }
50
+ destroy() {
51
+ this.view.dom
52
+ .querySelectorAll('[data-track-status="pending"], [data-track-status="accepted"]')
53
+ .forEach((dom) => {
54
+ var _a, _b;
55
+ if ((_b = (_a = dom.parentElement) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.classList.contains('keyword')) {
56
+ return;
57
+ }
58
+ dom.removeEventListener('click', this.listener);
59
+ });
60
+ }
61
+ addEventListener(view) {
62
+ view.dom
63
+ .querySelectorAll('[data-track-status="pending"], [data-track-status="accepted"]')
64
+ .forEach((dom) => {
65
+ var _a, _b;
66
+ if ((_b = (_a = dom.parentElement) === null || _a === void 0 ? void 0 : _a.parentElement) === null || _b === void 0 ? void 0 : _b.classList.contains('keyword')) {
67
+ return;
68
+ }
69
+ dom.addEventListener('click', this.listener);
70
+ });
71
+ }
72
+ }
73
+ const getTrackChangesData = (node) => {
74
+ var _a;
75
+ const trackChangesMark = node.marks.find((mark) => (mark.type.name === 'tracked_insert' ||
76
+ mark.type.name === 'tracked_delete') &&
77
+ mark.attrs.dataTracked);
78
+ return (_a = trackChangesMark === null || trackChangesMark === void 0 ? void 0 : trackChangesMark.attrs) === null || _a === void 0 ? void 0 : _a.dataTracked;
79
+ };
80
+ export const SET_SUGGESTION_ID = 'SET_SELECTED_SUGGESTION_ID';
81
+ const CLEAR_SUGGESTION_ID = 'CLEAR_SUGGESTION_ID';
82
+ export const selectedSuggestionKey = new PluginKey('selected_suggestion');
83
+ export default (props) => new Plugin({
84
+ key: selectedSuggestionKey,
85
+ view: (view) => new SuggestionView(view),
86
+ state: {
87
+ init: () => DecorationSet.empty,
88
+ apply: (tr, value, _, state) => {
89
+ const suggestionId = tr.getMeta(SET_SUGGESTION_ID);
90
+ if (suggestionId) {
91
+ return buildSelectedSuggestionDecoration(suggestionId, state, props);
92
+ }
93
+ if (tr.getMeta(CLEAR_SUGGESTION_ID) ||
94
+ tr.getMeta('track-changes-refresh-changes')) {
95
+ props.setEditorSelectedSuggestion(undefined);
96
+ return DecorationSet.empty;
97
+ }
98
+ return value;
99
+ },
100
+ },
101
+ props: {
102
+ handleClick(view, pos) {
103
+ const nodeClicked = view.state.doc.nodeAt(pos);
104
+ const trackChangesData = nodeClicked && getTrackChangesData(nodeClicked);
105
+ if (!trackChangesData) {
106
+ view.dispatch(view.state.tr.setMeta(CLEAR_SUGGESTION_ID, true));
107
+ props.setEditorSelectedSuggestion(undefined);
108
+ }
109
+ },
110
+ decorations: (state) => selectedSuggestionKey.getState(state),
111
+ },
112
+ });
113
+ const buildSelectedSuggestionDecoration = (suggestionId, state, props) => {
114
+ var _a;
115
+ const change = (_a = trackChangesPluginKey
116
+ .getState(state)) === null || _a === void 0 ? void 0 : _a.changeSet.get(suggestionId);
117
+ const decorations = [];
118
+ if (change) {
119
+ const decoration = change.type === 'text-change' ? Decoration.inline : Decoration.node;
120
+ decorations.push(decoration(change.from, change.to, {
121
+ class: 'selected-suggestion',
122
+ }));
123
+ props.setEditorSelectedSuggestion(change.id);
124
+ }
125
+ return DecorationSet.create(state.doc, decorations);
126
+ };
@@ -36,10 +36,12 @@ export class AffiliationView extends BaseNodeView {
36
36
  this.dom.setAttribute('style', 'order: ' + (order || (pluginState === null || pluginState === void 0 ? void 0 : pluginState.affiliations.length) + 1));
37
37
  }
38
38
  if ((_a = attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length) {
39
+ this.dom.setAttribute('data-track-id', attrs.dataTracked[0].id);
39
40
  this.dom.setAttribute('data-track-status', attrs.dataTracked[0].status);
40
41
  this.dom.setAttribute('data-track-op', attrs.dataTracked[0].operation);
41
42
  }
42
43
  else {
44
+ this.dom.removeAttribute('data-track-id');
43
45
  this.dom.removeAttribute('data-track-status');
44
46
  this.dom.removeAttribute('data-track-type');
45
47
  }
@@ -51,7 +53,6 @@ export class AffiliationView extends BaseNodeView {
51
53
  this.updateContents();
52
54
  };
53
55
  this.ignoreMutation = () => true;
54
- this.stopEvent = () => true;
55
56
  this.formatAddress = (affiliation) => {
56
57
  const { department, institution, addressLine1, city, county, country, postCode, } = affiliation;
57
58
  return [
@@ -26,9 +26,10 @@ import { CHANGE_OPERATION, CHANGE_STATUS, } from '@manuscripts/track-changes-plu
26
26
  import { buildComment, Decoder, } from '@manuscripts/transform';
27
27
  import { commentIcon, editIcon } from '../assets';
28
28
  import { sanitize } from '../lib/dompurify';
29
+ import { getAttrsTrackingButton, getChangeClasses, } from '../lib/track-changes-utils';
29
30
  import { getBibliographyPluginState } from '../plugins/bibliography';
30
31
  import { commentAnnotation } from '../plugins/comment_annotation';
31
- import { getAttrsTrackingButton, getMarkDecoration, } from '../plugins/tracking-mark';
32
+ import { selectedSuggestionKey, SET_SUGGESTION_ID, } from '../plugins/selected-suggestion-ui';
32
33
  import BlockView from './block_view';
33
34
  import { createNodeView } from './creators';
34
35
  import ReactSubView from './ReactSubView';
@@ -55,11 +56,13 @@ export class BibliographyElementBlockView extends BlockView {
55
56
  this.updateContents = () => __awaiter(this, void 0, void 0, function* () {
56
57
  const bib = getBibliographyPluginState(this.view.state);
57
58
  const commentsDecorationSet = commentAnnotation.getState(this.view.state);
59
+ const selectedSuggestion = selectedSuggestionKey.getState(this.view.state);
58
60
  const commentElementMap = new Map();
59
61
  const dataTrackedMap = new Map();
62
+ let selectedBibItemSuggestion;
60
63
  this.node.descendants((node, pos) => {
64
+ const nodePosition = this.getPos() + pos + 2;
61
65
  if (commentsDecorationSet) {
62
- const nodePosition = this.getPos() + pos + 2;
63
66
  const commentWidget = commentsDecorationSet.find(nodePosition, nodePosition);
64
67
  if (commentWidget.length) {
65
68
  const commentElement = commentWidget[0].type.toDOM();
@@ -71,6 +74,10 @@ export class BibliographyElementBlockView extends BlockView {
71
74
  const lastChange = dataTracked[dataTracked.length - 1];
72
75
  dataTrackedMap.set(node.attrs.id, lastChange);
73
76
  }
77
+ if ((dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.length) &&
78
+ (selectedSuggestion === null || selectedSuggestion === void 0 ? void 0 : selectedSuggestion.find(nodePosition, nodePosition + node.nodeSize).length)) {
79
+ selectedBibItemSuggestion = node.attrs.id;
80
+ }
74
81
  });
75
82
  const can = this.props.getCapabilities();
76
83
  const wrapper = document.createElement('div');
@@ -108,13 +115,16 @@ export class BibliographyElementBlockView extends BlockView {
108
115
  }
109
116
  const dataTracked = dataTrackedMap.get(element.id);
110
117
  if (dataTracked) {
111
- element.classList.add('attrs-track-mark');
112
- const decoration = getMarkDecoration(dataTracked);
113
- decoration.style && element.setAttribute('style', decoration.style);
118
+ element.classList.add('attrs-track-mark', ...getChangeClasses([dataTracked]));
114
119
  if (dataTracked.status === CHANGE_STATUS.pending &&
115
120
  dataTracked.operation === CHANGE_OPERATION.set_node_attributes) {
116
121
  element.appendChild(getAttrsTrackingButton(dataTracked.id));
117
122
  }
123
+ this.addClickListenerToBibItem(element, dataTracked);
124
+ }
125
+ if (selectedBibItemSuggestion &&
126
+ selectedBibItemSuggestion === element.id) {
127
+ element.classList.add('selected-suggestion');
118
128
  }
119
129
  wrapper.append(element);
120
130
  }
@@ -140,6 +150,13 @@ export class BibliographyElementBlockView extends BlockView {
140
150
  this.handleDelete = (item) => {
141
151
  return this.deleteNode(item._id);
142
152
  };
153
+ this.addClickListenerToBibItem = (element, dataTracked) => {
154
+ if (dataTracked.status !== CHANGE_STATUS.rejected) {
155
+ element.addEventListener('click', () => {
156
+ this.view.dispatch(this.view.state.tr.setMeta(SET_SUGGESTION_ID, dataTracked.id));
157
+ });
158
+ }
159
+ };
143
160
  }
144
161
  }
145
162
  export default createNodeView(BibliographyElementBlockView);
@@ -41,7 +41,10 @@ export class CitationView extends BaseNodeView {
41
41
  this.updateContents = () => {
42
42
  const bib = getBibliographyPluginState(this.view.state);
43
43
  const citation = this.getCitation();
44
- const classes = ['citation', ...getChangeClasses(this.node)];
44
+ const classes = [
45
+ 'citation',
46
+ ...getChangeClasses(this.node.attrs.dataTracked),
47
+ ];
45
48
  const element = document.createElement('span');
46
49
  element.className = classes.join(' ');
47
50
  const text = bib.renderedCitations.get(citation._id);
@@ -2,6 +2,7 @@ import { SecondaryButton } from '@manuscripts/style-guide';
2
2
  import { isContributorNode } from '@manuscripts/transform';
3
3
  import { getActualAttrs } from '../lib/track-changes-utils';
4
4
  import { affiliationsKey } from '../plugins/affiliations';
5
+ import { selectedSuggestionKey } from '../plugins/selected-suggestion-ui';
5
6
  import BlockView from './block_view';
6
7
  import { createNodeView } from './creators';
7
8
  import ReactSubView from './ReactSubView';
@@ -25,12 +26,17 @@ export class ContributorsView extends BlockView {
25
26
  };
26
27
  this.buildAuthors = () => {
27
28
  var _a;
29
+ const selectedSuggestion = selectedSuggestionKey.getState(this.view.state);
30
+ let selectedAuthor;
28
31
  const authors = [];
29
32
  const authorsWrapper = document.createElement('div');
30
33
  authorsWrapper.classList.add('contributors-list');
31
- (_a = this.node.content) === null || _a === void 0 ? void 0 : _a.forEach((node) => {
34
+ (_a = this.node.content) === null || _a === void 0 ? void 0 : _a.forEach((node, offset) => {
32
35
  if (isContributorNode(node)) {
33
36
  authors.push(node);
37
+ if (selectedSuggestion === null || selectedSuggestion === void 0 ? void 0 : selectedSuggestion.find(this.getPos() + offset + 2, this.getPos() + offset + node.nodeSize + 2).length) {
38
+ selectedAuthor = node.attrs.id;
39
+ }
34
40
  }
35
41
  });
36
42
  authors
@@ -40,11 +46,11 @@ export class ContributorsView extends BlockView {
40
46
  return;
41
47
  }
42
48
  const jointAuthors = this.isJointFirstAuthor(authors, i);
43
- authorsWrapper.appendChild(this.buildAuthor(author, jointAuthors));
49
+ authorsWrapper.appendChild(this.buildAuthor(author, jointAuthors, selectedAuthor));
44
50
  });
45
51
  this.container.appendChild(authorsWrapper);
46
52
  };
47
- this.buildAuthor = (node, isJointFirstAuthor) => {
53
+ this.buildAuthor = (node, isJointFirstAuthor, selectedAuthor) => {
48
54
  var _a;
49
55
  const pluginState = affiliationsKey.getState(this.view.state);
50
56
  const attrs = node.attrs;
@@ -54,10 +60,12 @@ export class ContributorsView extends BlockView {
54
60
  container.setAttribute('id', attrs.id);
55
61
  container.setAttribute('contenteditable', 'false');
56
62
  if ((_a = attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length) {
63
+ container.setAttribute('data-track-id', attrs.dataTracked[0].id);
57
64
  container.setAttribute('data-track-status', attrs.dataTracked[0].status);
58
65
  container.setAttribute('data-track-op', attrs.dataTracked[0].operation);
59
66
  }
60
67
  else {
68
+ container.removeAttribute('data-track-id');
61
69
  container.removeAttribute('data-track-status');
62
70
  container.removeAttribute('data-track-type');
63
71
  }
@@ -94,6 +102,9 @@ export class ContributorsView extends BlockView {
94
102
  if (displayAttr.isCorresponding) {
95
103
  container.appendChild(this.createNote('*', 'Corresponding author'));
96
104
  }
105
+ if (selectedAuthor && selectedAuthor === attrs.id) {
106
+ container.classList.add('selected-suggestion');
107
+ }
97
108
  return container;
98
109
  };
99
110
  this.initials = (given) => given
@@ -33,7 +33,10 @@ export class CrossReferenceView extends BaseNodeView {
33
33
  });
34
34
  };
35
35
  this.updateContents = () => {
36
- const nodeClasses = ['cross-reference', ...getChangeClasses(this.node)];
36
+ const nodeClasses = [
37
+ 'cross-reference',
38
+ ...getChangeClasses(this.node.attrs.dataTracked),
39
+ ];
37
40
  this.dom.className = nodeClasses.join(' ');
38
41
  this.dom.textContent = this.node.attrs.customLabel || this.node.attrs.label;
39
42
  this.dom.addEventListener('click', this.handleClick);
@@ -39,10 +39,14 @@ export class KeywordView extends BaseNodeView {
39
39
  this.contentDOM = document.createElement('span');
40
40
  };
41
41
  this.updateContents = () => {
42
- const keyword = document.createElement('span');
43
- const classes = ['keyword', ...getChangeClasses(this.node)];
44
- keyword.classList.add(...classes);
45
- keyword.appendChild(this.contentDOM);
42
+ var _a;
43
+ const classes = [
44
+ 'keyword',
45
+ ...getChangeClasses(this.node.attrs.dataTracked),
46
+ ];
47
+ this.dom.className = classes.join(' ');
48
+ this.dom.innerHTML = '';
49
+ this.dom.appendChild(this.contentDOM);
46
50
  const can = this.props.getCapabilities();
47
51
  if (can.editArticle) {
48
52
  const svg = new DOMParser()
@@ -50,10 +54,16 @@ export class KeywordView extends BaseNodeView {
50
54
  .querySelector('svg');
51
55
  svg.classList.add('delete-keyword');
52
56
  svg.addEventListener('click', this.showConfirmationDialog);
53
- keyword.appendChild(svg);
57
+ this.dom.appendChild(svg);
58
+ }
59
+ if ((_a = this.node.attrs.dataTracked) === null || _a === void 0 ? void 0 : _a.length) {
60
+ this.dom.setAttribute('data-track-id', this.node.attrs.dataTracked[0].id);
61
+ this.dom.setAttribute('data-track-status', this.node.attrs.dataTracked[0].status);
62
+ }
63
+ else {
64
+ this.dom.removeAttribute('data-track-id');
65
+ this.dom.removeAttribute('data-track-status');
54
66
  }
55
- this.dom.innerHTML = '';
56
- this.dom.appendChild(keyword);
57
67
  };
58
68
  this.showConfirmationDialog = () => {
59
69
  var _a;
@@ -15,3 +15,4 @@
15
15
  */
16
16
  export declare const editIcon = "\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 14 14\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M8.706 2.33624L11.553 5.19824L4.345 12.4422L1.498 9.58124L8.706 2.33624V2.33624ZM13.714 1.64624L12.444 0.37024C12.3273 0.253047 12.1886 0.160056 12.0359 0.0966039C11.8831 0.0331518 11.7194 0.000488281 11.554 0.000488281C11.3886 0.000488281 11.2249 0.0331518 11.0721 0.0966039C10.9194 0.160056 10.7807 0.253047 10.664 0.37024L9.447 1.59224L12.295 4.45424L13.715 3.02824C13.8976 2.84462 14.0001 2.59619 14.0001 2.33724C14.0001 2.07829 13.8976 1.82986 13.715 1.64624H13.714ZM0.00800253 13.6032C-0.00418388 13.6571 -0.00246802 13.7131 0.0129883 13.7661C0.0284447 13.819 0.0571327 13.8672 0.096349 13.906C0.135565 13.9448 0.184019 13.973 0.237143 13.9879C0.290268 14.0028 0.346315 14.004 0.400003 13.9912L3.573 13.2172L0.727003 10.3552L0.0070026 13.6032H0.00800253Z\"\n fill=\"#6E6E6E\"\n />\n </svg>\n";
17
17
  export declare const commentIcon = "\n<svg\n width=\"20\"\n height=\"15\"\n viewBox=\"0 0 20 15\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n fill-rule=\"evenodd\"\n clip-rule=\"evenodd\"\n d=\"M7.94841 4.18311C7.98238 3.9602 8 3.73191 8 3.49951C8 3.22073 7.97465 2.94787 7.92613 2.68311H13.5C14.8854 2.68311 16.25 3.6425 16.25 5.09977V9.02453L19.1086 12.9949C19.2731 13.2233 19.2958 13.5245 19.1675 13.775C19.0392 14.0255 18.7814 14.1831 18.5 14.1831H5.5C4.11463 14.1831 2.75 13.2237 2.75 11.7664V7.93729C2.9939 7.97821 3.24446 7.99951 3.5 7.99951C3.75553 7.99951 4.00609 7.97821 4.25 7.93729V11.7664C4.25 12.1508 4.67537 12.6831 5.5 12.6831H17.0358L14.8913 9.70467C14.7994 9.57703 14.75 9.42372 14.75 9.26644V5.09977C14.75 4.71538 14.3246 4.18311 13.5 4.18311H7.94841Z\"\n fill=\"#FFBD26\"\n />\n <path\n d=\"M11.5 6.99951H8.5\"\n stroke=\"#FFBD26\"\n stroke-width=\"1.5\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M12 9.99951H7\"\n stroke=\"#FFBD26\"\n stroke-width=\"1.5\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M3.5 1L3.5 6\"\n stroke=\"#FFBD26\"\n stroke-width=\"1.5\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M6 3.5L1 3.5\"\n stroke=\"#FFBD26\"\n stroke-width=\"1.5\"\n stroke-miterlimit=\"10\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n";
18
+ export declare const editAttrsTrackingIcon = "\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M12 2L14 4L9 9L6 10L7 7L12 2Z\"\n stroke=\"#353535\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n <path\n d=\"M13 10V11.5C13 12.328 12.328 13 11.5 13H4.5C3.672 13 3 12.328 3 11.5V4.5C3 3.672 3.672 3 4.5 3H6\"\n stroke=\"#353535\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n";
@@ -28,7 +28,7 @@ interface PluginProps {
28
28
  deleteModel: (id: string) => Promise<string>;
29
29
  setComment: (comment?: CommentAnnotation) => void;
30
30
  setSelectedComment: (id?: string) => void;
31
- setEditorSelectedSuggestion?: (id?: string) => void;
31
+ setEditorSelectedSuggestion: (id?: string) => void;
32
32
  getCapabilities: () => Capabilities;
33
33
  plugins?: Plugin<ManuscriptSchema>[];
34
34
  cslProps: CSLProps;
@@ -26,6 +26,7 @@ export { PopperManager } from './lib/popper';
26
26
  export * from './toolbar';
27
27
  export * from './plugins/highlight';
28
28
  export { commentScroll, isThereSelector, isHighlightComment, } from './plugins/comment_annotation';
29
+ export { SET_SUGGESTION_ID } from './plugins/selected-suggestion-ui';
29
30
  export * from './lib/utils';
30
31
  export * from './lib/track-changes-utils';
31
32
  export * from './useEditor';
@@ -13,6 +13,7 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
+ import { TrackedAttrs } from '@manuscripts/track-changes-plugin';
16
17
  import { ManuscriptNode } from '@manuscripts/transform';
17
18
  import { Node as ProsemirrorNode } from 'prosemirror-model';
18
19
  export declare function isRejectedInsert(node: ProsemirrorNode): boolean;
@@ -20,6 +21,7 @@ export declare function isDeleted(node: ProsemirrorNode): boolean;
20
21
  export declare function isPendingInsert(node: ProsemirrorNode): boolean;
21
22
  export declare function isPending(node: ProsemirrorNode): boolean;
22
23
  export declare function isPendingSetAttrs(node: ProsemirrorNode): boolean;
23
- export declare function getChangeClasses(node: ProsemirrorNode): string[];
24
+ export declare function getChangeClasses(dataTracked?: TrackedAttrs[]): string[];
24
25
  export declare function isTracked(node: ProsemirrorNode): boolean;
25
26
  export declare function getActualAttrs<T extends ManuscriptNode>(node: T): T["attrs"];
27
+ export declare const getAttrsTrackingButton: (changeID: string) => HTMLButtonElement;
@@ -13,10 +13,12 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { TrackChangesState } from '@manuscripts/track-changes-plugin';
17
- import { Plugin } from 'prosemirror-state';
18
- interface TrackChangesProps {
19
- setEditorSelectedSuggestion?: (id?: string) => void;
16
+ import { Plugin, PluginKey } from 'prosemirror-state';
17
+ import { DecorationSet } from 'prosemirror-view';
18
+ interface SelectedSuggestionProps {
19
+ setEditorSelectedSuggestion: (id?: string) => void;
20
20
  }
21
- declare const _default: (props: TrackChangesProps) => Plugin<TrackChangesState>;
21
+ export declare const SET_SUGGESTION_ID = "SET_SELECTED_SUGGESTION_ID";
22
+ export declare const selectedSuggestionKey: PluginKey<DecorationSet>;
23
+ declare const _default: (props: SelectedSuggestionProps) => Plugin<DecorationSet>;
22
24
  export default _default;
@@ -24,7 +24,6 @@ export declare class AffiliationView<PropsType extends BaseNodeProps> extends Ba
24
24
  updateContents: () => void;
25
25
  protected createDOM: () => void;
26
26
  ignoreMutation: () => boolean;
27
- stopEvent: () => boolean;
28
27
  formatAddress: (affiliation: AffiliationNode['attrs']) => string;
29
28
  }
30
29
  declare const _default: (props: BaseNodeProps, dispatch?: import("..").Dispatch | undefined) => import("../types").NodeViewCreator<AffiliationView<any>>;
@@ -24,6 +24,7 @@ export interface BaseNodeProps {
24
24
  getModelMap: () => Map<string, Model>;
25
25
  popper: PopperManager;
26
26
  cslProps: CSLProps;
27
+ setEditorSelectedSuggestion: (id?: string) => void;
27
28
  }
28
29
  export declare class BaseNodeView<PropsType extends BaseNodeProps> implements NodeView {
29
30
  readonly props: PropsType;
@@ -32,6 +32,7 @@ export declare class BibliographyElementBlockView<PropsType extends Bibliography
32
32
  createElement: () => void;
33
33
  private handleSave;
34
34
  private handleDelete;
35
+ private addClickListenerToBibItem;
35
36
  }
36
37
  declare const _default: (props: BaseNodeProps, dispatch?: import("..").Dispatch | undefined) => import("../types").NodeViewCreator<BibliographyElementBlockView<any>>;
37
38
  export default _default;
@@ -13,7 +13,7 @@ export declare class ContributorsView<PropsType extends ContributorsProps> exten
13
13
  buildAuthors: () => void;
14
14
  container: HTMLElement;
15
15
  inner: HTMLElement;
16
- buildAuthor: (node: ContributorNode, isJointFirstAuthor: boolean) => HTMLButtonElement;
16
+ buildAuthor: (node: ContributorNode, isJointFirstAuthor: boolean, selectedAuthor?: string) => HTMLButtonElement;
17
17
  createNote(text?: string, title?: string): HTMLSpanElement;
18
18
  initials: (given: string) => string;
19
19
  buildNameLiteral: ({ given, family, suffix }: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@manuscripts/body-editor",
3
3
  "description": "Prosemirror components for editing and viewing manuscripts",
4
- "version": "1.7.3",
4
+ "version": "1.7.5",
5
5
  "repository": "github:Atypon-OpenSource/manuscripts-body-editor",
6
6
  "license": "Apache-2.0",
7
7
  "main": "dist/cjs",
@@ -571,7 +571,7 @@ Next levels are shifted 'up' by 1
571
571
  background-color: inherit !important;
572
572
  }
573
573
 
574
- .keywords .keyword:hover {
574
+ .keywords .keyword:hover:not(.pending) {
575
575
  background-color: #f2fbfc !important;
576
576
  }
577
577
 
@@ -688,8 +688,19 @@ Next levels are shifted 'up' by 1
688
688
  --selection-bg-color: #bce7f6;
689
689
  }
690
690
 
691
- .ProseMirror ::selection {
692
- background: var(--selection-bg-color);
691
+ .selected-suggestion::selection {
692
+ background: none;
693
+ }
694
+
695
+ .selected-suggestion {
696
+ background: #BCE7F6 !important;
697
+ }
698
+
699
+ .selected-suggestion {
700
+ border-width: 2px 0 2px 0 !important;
701
+ border-color: #20AEDF !important;
702
+ border-radius: 3px !important;
703
+ border-style: solid !important;
693
704
  }
694
705
 
695
706
  .ProseMirror .inserted.pending {
@@ -880,3 +891,7 @@ Next levels are shifted 'up' by 1
880
891
  flex-direction: column;
881
892
  align-items: flex-start;
882
893
  }
894
+
895
+ * {
896
+ scroll-behavior: smooth;
897
+ }
package/styles/Editor.css CHANGED
@@ -1013,6 +1013,6 @@
1013
1013
  line-height: 1.43;
1014
1014
  padding-left: 65px;
1015
1015
  }
1016
- div[style*="background-color: rgba(249, 2, 2, 0.53)"] {
1017
- background-color: #ffe08b !important;
1016
+ .highlight {
1017
+ background-color: #ffeebf !important;
1018
1018
  }
@@ -1,104 +0,0 @@
1
- "use strict";
2
- /*!
3
- * © 2019 Atypon Systems LLC
4
- *
5
- * Licensed under the Apache License, Version 2.0 (the "License");
6
- * you may not use this file except in compliance with the License.
7
- * You may obtain a copy of the License at
8
- *
9
- * http://www.apache.org/licenses/LICENSE-2.0
10
- *
11
- * Unless required by applicable law or agreed to in writing, software
12
- * distributed under the License is distributed on an "AS IS" BASIS,
13
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
- * See the License for the specific language governing permissions and
15
- * limitations under the License.
16
- */
17
- Object.defineProperty(exports, "__esModule", { value: true });
18
- const track_changes_plugin_1 = require("@manuscripts/track-changes-plugin");
19
- const prosemirror_state_1 = require("prosemirror-state");
20
- const prosemirror_view_1 = require("prosemirror-view");
21
- const ACCEPT_BUTTON_XLINK = '#track-changes-action-accept';
22
- const REJECT_BUTTON_XLINK = '#track-changes-action-reject';
23
- const BASE_CLASS = 'track-changes';
24
- var CLASSES;
25
- (function (CLASSES) {
26
- CLASSES["focused"] = "focused";
27
- CLASSES["control"] = "control";
28
- })(CLASSES || (CLASSES = {}));
29
- const createControl = (change, action, xLink) => {
30
- return `
31
- <button type="button" data-action="${action}" data-changeid="${change.id}">
32
- <svg><use href="${xLink}"></use></svg>
33
- </button>
34
- `;
35
- };
36
- const getClassnames = (...types) => {
37
- return [BASE_CLASS].concat(types.filter(Boolean).map((type) => `${BASE_CLASS}--${type}`));
38
- };
39
- const addClassnamesToEl = (el, ...types) => {
40
- getClassnames(...types).forEach((classname) => el.classList.add(classname));
41
- };
42
- const geControlsPosition = (change) => {
43
- const NODE_OFFSET = {
44
- 'text-change': 0,
45
- 'wrap-change': 0,
46
- 'mark-change': 0,
47
- 'node-attr-change': 0,
48
- 'node-change-keyword': 1,
49
- };
50
- const offset = (change.type === 'node-change'
51
- ? NODE_OFFSET[`${change.type}-${change.nodeType}`]
52
- : NODE_OFFSET[change.type]) || 0;
53
- return change.to - offset;
54
- };
55
- const createControls = (change) => {
56
- return prosemirror_view_1.Decoration.widget(geControlsPosition(change), () => {
57
- const el = document.createElement('div');
58
- addClassnamesToEl(el, CLASSES.control);
59
- el.dataset.changeid = change.id;
60
- el.innerHTML =
61
- createControl(change, 'reject', REJECT_BUTTON_XLINK) +
62
- createControl(change, 'accept', ACCEPT_BUTTON_XLINK);
63
- return el;
64
- }, { side: -1 });
65
- };
66
- const decorateChanges = (state) => {
67
- const pluginState = track_changes_plugin_1.trackChangesPluginKey.getState(state);
68
- if (!pluginState) {
69
- return [];
70
- }
71
- const { pending } = pluginState.changeSet;
72
- return pending.reduce((decorations, change) => {
73
- if (change.id === null) {
74
- return decorations;
75
- }
76
- return [...decorations, createControls(change)];
77
- }, []);
78
- };
79
- const getTrackChangesData = (node) => {
80
- var _a;
81
- const trackChangesMark = node.marks.find((mark) => (mark.type.name === 'tracked_insert' ||
82
- mark.type.name === 'tracked_delete') &&
83
- mark.attrs.dataTracked);
84
- return (_a = trackChangesMark === null || trackChangesMark === void 0 ? void 0 : trackChangesMark.attrs) === null || _a === void 0 ? void 0 : _a.dataTracked;
85
- };
86
- exports.default = (props) => new prosemirror_state_1.Plugin({
87
- props: {
88
- handleClick(view, pos) {
89
- if (props.setEditorSelectedSuggestion) {
90
- const nodeClicked = view.state.doc.nodeAt(pos);
91
- const trackChangesData = nodeClicked && getTrackChangesData(nodeClicked);
92
- if (trackChangesData) {
93
- props.setEditorSelectedSuggestion(trackChangesData.id);
94
- }
95
- else {
96
- props.setEditorSelectedSuggestion(undefined);
97
- }
98
- }
99
- },
100
- decorations: (state) => {
101
- return prosemirror_view_1.DecorationSet.create(state.doc, decorateChanges(state));
102
- },
103
- },
104
- });