@manuscripts/body-editor 2.5.6-date-fix.0 → 2.5.7

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 (93) hide show
  1. package/dist/cjs/commands.js +121 -211
  2. package/dist/cjs/components/views/DeleteFootnoteDialog.js +2 -2
  3. package/dist/cjs/components/views/FootnotesSelector.js +18 -19
  4. package/dist/cjs/configs/ManuscriptsEditor.js +2 -1
  5. package/dist/cjs/configs/editor-plugins.js +0 -2
  6. package/dist/cjs/configs/editor-views.js +6 -4
  7. package/dist/cjs/icons.js +8 -0
  8. package/dist/cjs/index.js +1 -0
  9. package/dist/cjs/lib/comments.js +5 -1
  10. package/dist/cjs/lib/context-menu.js +21 -101
  11. package/dist/cjs/lib/doc.js +27 -4
  12. package/dist/cjs/lib/footnotes.js +31 -122
  13. package/dist/cjs/lib/plugins.js +8 -0
  14. package/dist/cjs/menus.js +1 -1
  15. package/dist/cjs/plugins/affiliations.js +2 -1
  16. package/dist/cjs/plugins/comments.js +10 -8
  17. package/dist/cjs/plugins/footnotes.js +188 -0
  18. package/dist/cjs/plugins/persist.js +4 -4
  19. package/dist/cjs/plugins/placeholder.js +19 -12
  20. package/dist/cjs/testing/default-editor-data.js +1 -1
  21. package/dist/cjs/testing/setup-editor.js +1 -0
  22. package/dist/cjs/versions.js +1 -1
  23. package/dist/cjs/views/editable_block.js +1 -1
  24. package/dist/cjs/views/footnote.js +117 -13
  25. package/dist/cjs/views/footnotes_element.js +10 -2
  26. package/dist/cjs/views/general_table_footnote.js +83 -0
  27. package/dist/cjs/views/inline_footnote.js +74 -124
  28. package/dist/cjs/views/table_element_footer.js +2 -5
  29. package/dist/es/commands.js +118 -207
  30. package/dist/es/components/views/DeleteFootnoteDialog.js +2 -2
  31. package/dist/es/components/views/FootnotesSelector.js +18 -19
  32. package/dist/es/configs/ManuscriptsEditor.js +2 -1
  33. package/dist/es/configs/editor-plugins.js +0 -2
  34. package/dist/es/configs/editor-views.js +4 -2
  35. package/dist/es/icons.js +5 -0
  36. package/dist/es/index.js +1 -0
  37. package/dist/es/lib/comments.js +3 -0
  38. package/dist/es/lib/context-menu.js +24 -101
  39. package/dist/es/lib/doc.js +25 -4
  40. package/dist/es/lib/footnotes.js +28 -116
  41. package/dist/es/lib/plugins.js +4 -0
  42. package/dist/es/menus.js +1 -1
  43. package/dist/es/plugins/affiliations.js +2 -1
  44. package/dist/es/plugins/comments.js +11 -9
  45. package/dist/es/plugins/footnotes.js +185 -0
  46. package/dist/es/plugins/persist.js +4 -4
  47. package/dist/es/plugins/placeholder.js +20 -11
  48. package/dist/es/testing/default-editor-data.js +1 -1
  49. package/dist/es/testing/setup-editor.js +1 -0
  50. package/dist/es/versions.js +1 -1
  51. package/dist/es/views/editable_block.js +1 -1
  52. package/dist/es/views/footnote.js +118 -13
  53. package/dist/es/views/footnotes_element.js +10 -2
  54. package/dist/es/views/general_table_footnote.js +76 -0
  55. package/dist/es/views/inline_footnote.js +78 -128
  56. package/dist/es/views/table_element_footer.js +4 -5
  57. package/dist/types/commands.d.ts +10 -14
  58. package/dist/types/components/views/DeleteFootnoteDialog.d.ts +2 -2
  59. package/dist/types/components/views/FootnotesSelector.d.ts +7 -7
  60. package/dist/types/configs/editor-views.d.ts +22 -35
  61. package/dist/types/icons.d.ts +2 -0
  62. package/dist/types/index.d.ts +1 -0
  63. package/dist/types/lib/comments.d.ts +1 -0
  64. package/dist/types/lib/context-menu.d.ts +1 -3
  65. package/dist/types/lib/doc.d.ts +2 -0
  66. package/dist/types/lib/footnotes.d.ts +8 -19
  67. package/dist/types/lib/plugins.d.ts +3 -0
  68. package/dist/types/plugins/{footnotes/index.d.ts → footnotes.d.ts} +14 -11
  69. package/dist/types/plugins/placeholder.d.ts +0 -2
  70. package/dist/types/versions.d.ts +1 -1
  71. package/dist/types/views/footnote.d.ts +14 -6
  72. package/dist/types/views/footnotes_element.d.ts +1 -0
  73. package/dist/types/views/{table_element_footer_editable.d.ts → general_table_footnote.d.ts} +11 -2
  74. package/dist/types/views/inline_footnote.d.ts +8 -14
  75. package/dist/types/views/table_element_footer.d.ts +2 -2
  76. package/package.json +3 -3
  77. package/styles/Editor.css +35 -64
  78. package/dist/cjs/plugins/footnotes/index.js +0 -215
  79. package/dist/cjs/plugins/footnotes/widgets.js +0 -136
  80. package/dist/cjs/plugins/table-footnote.js +0 -46
  81. package/dist/cjs/views/footnote_editable.js +0 -21
  82. package/dist/cjs/views/footnotes_element_editable.js +0 -22
  83. package/dist/cjs/views/table_element_footer_editable.js +0 -20
  84. package/dist/es/plugins/footnotes/index.js +0 -211
  85. package/dist/es/plugins/footnotes/widgets.js +0 -127
  86. package/dist/es/plugins/table-footnote.js +0 -44
  87. package/dist/es/views/footnote_editable.js +0 -19
  88. package/dist/es/views/footnotes_element_editable.js +0 -20
  89. package/dist/es/views/table_element_footer_editable.js +0 -18
  90. package/dist/types/plugins/footnotes/widgets.d.ts +0 -22
  91. package/dist/types/plugins/table-footnote.d.ts +0 -3
  92. package/dist/types/views/footnote_editable.d.ts +0 -51
  93. package/dist/types/views/footnotes_element_editable.d.ts +0 -51
@@ -13,30 +13,40 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
+ import { isFootnoteNode, isGeneralTableFootnoteNode, } from '@manuscripts/transform';
16
17
  import { Plugin, TextSelection } from 'prosemirror-state';
17
18
  import { Decoration, DecorationSet } from 'prosemirror-view';
18
- export const placeholderWidget = (placeholder) => (view, getPos) => {
19
+ const placeholderWidget = (placeholder) => (view, getPos) => {
19
20
  const element = document.createElement('span');
20
21
  element.className = 'placeholder-text';
21
22
  element.textContent = placeholder;
22
23
  element.addEventListener('click', (event) => {
23
24
  event.preventDefault();
24
- view.dispatch(view.state.tr.setSelection(TextSelection.create(view.state.tr.doc, getPos())));
25
+ const pos = getPos();
26
+ const selection = TextSelection.create(view.state.tr.doc, pos);
27
+ view.dispatch(view.state.tr.setSelection(selection));
25
28
  });
26
29
  return element;
27
30
  };
31
+ const getParagraphPlaceholderText = (parent) => {
32
+ if (!parent || parent.textContent.length) {
33
+ return;
34
+ }
35
+ if (isFootnoteNode(parent) || isGeneralTableFootnoteNode(parent)) {
36
+ return 'Type new footnote here';
37
+ }
38
+ };
28
39
  export default () => new Plugin({
29
40
  props: {
30
41
  decorations: (state) => {
31
42
  const decorations = [];
32
- const decorate = (node, pos) => {
33
- const { placeholder } = node.attrs;
34
- if (placeholder &&
35
- !node.isAtom &&
36
- node.type.isBlock &&
37
- node.childCount === 0) {
43
+ state.doc.descendants((node, pos, parent) => {
44
+ if (!node.isAtom && node.type.isBlock && node.childCount === 0) {
38
45
  if (node.type === node.type.schema.nodes.paragraph) {
39
- decorations.push(Decoration.widget(pos + 1, placeholderWidget(placeholder)));
46
+ const text = getParagraphPlaceholderText(parent);
47
+ if (text) {
48
+ decorations.push(Decoration.widget(pos + 1, placeholderWidget(text)));
49
+ }
40
50
  }
41
51
  else {
42
52
  decorations.push(Decoration.node(pos, pos + node.nodeSize, {
@@ -44,8 +54,7 @@ export default () => new Plugin({
44
54
  }));
45
55
  }
46
56
  }
47
- };
48
- state.doc.descendants(decorate);
57
+ });
49
58
  return DecorationSet.create(state.doc, decorations);
50
59
  },
51
60
  },
@@ -68,7 +68,7 @@ export const defaultEditorProps = {
68
68
  upload: () => { },
69
69
  download: () => { },
70
70
  },
71
- getCapabilities: () => getAllPermitted(),
71
+ getCapabilities: () => (Object.assign(Object.assign({}, getAllPermitted()), { editWithoutTracking: true })),
72
72
  cslProps: {
73
73
  style: '',
74
74
  locale: '',
@@ -48,6 +48,7 @@ export function setupEditor() {
48
48
  left: 0,
49
49
  right: 0,
50
50
  },
51
+ handleScrollToSelection: () => true,
51
52
  nodeViews: createNodeViews(props, () => { }),
52
53
  });
53
54
  return ProsemirrorTestChain.of(view);
@@ -1,2 +1,2 @@
1
- export const VERSION = '2.5.6-date-fix.0';
1
+ export const VERSION = '2.5.7';
2
2
  export const MATHJAX_VERSION = '3.2.2';
@@ -68,7 +68,7 @@ export const EditableBlock = (Base) => {
68
68
  this.createMenu = () => {
69
69
  return new ContextMenu(this.node, this.view, this.getPos, {
70
70
  addComment: true,
71
- }, this.props);
71
+ });
72
72
  };
73
73
  }
74
74
  };
@@ -13,22 +13,127 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
- import { getChangeClasses } from '../lib/track-changes-utils';
17
- import BlockView from './block_view';
18
- import { createNodeOrElementView } from './creators';
19
- export class FootnoteView extends BlockView {
16
+ import { schema } from '@manuscripts/transform';
17
+ import { isEqual } from 'lodash';
18
+ import { NodeSelection } from 'prosemirror-state';
19
+ import { findParentNodeOfTypeClosestToPos } from 'prosemirror-utils';
20
+ import { DeleteFootnoteDialog, } from '../components/views/DeleteFootnoteDialog';
21
+ import { alertIcon, deleteIcon } from '../icons';
22
+ import { getFootnotesElementState } from '../lib/footnotes';
23
+ import { getChangeClasses, isDeleted } from '../lib/track-changes-utils';
24
+ import { BaseNodeView } from './base_node_view';
25
+ import { createNodeView } from './creators';
26
+ import ReactSubView from './ReactSubView';
27
+ export class FootnoteView extends BaseNodeView {
20
28
  constructor() {
21
29
  super(...arguments);
22
- this.elementType = 'div';
30
+ this.initialise = () => {
31
+ this.dom = document.createElement('div');
32
+ this.contentDOM = document.createElement('div');
33
+ this.contentDOM.classList.add('footnote-text');
34
+ this.updateContents();
35
+ };
36
+ this.updateContents = () => {
37
+ const id = this.node.attrs.id;
38
+ const fn = getFootnotesElementState(this.view.state, id);
39
+ if (!fn) {
40
+ return;
41
+ }
42
+ const marker = document.createElement('span');
43
+ if (!isDeleted(this.node) && fn.unusedFootnoteIDs.has(id)) {
44
+ marker.classList.add('uncited-footnote');
45
+ marker.innerHTML = alertIcon;
46
+ }
47
+ else {
48
+ marker.classList.add('footnote-marker');
49
+ marker.innerText = fn.labels.get(id) || '';
50
+ marker.addEventListener('mousedown', (e) => this.handleMarkerClick(e));
51
+ }
52
+ const deleteBtn = document.createElement('span');
53
+ deleteBtn.classList.add('delete-icon');
54
+ deleteBtn.innerHTML = deleteIcon;
55
+ deleteBtn.addEventListener('mousedown', (e) => this.handleDeleteClick(e));
56
+ this.dom.innerHTML = '';
57
+ this.dom.classList.value = '';
58
+ this.dom.classList.add('footnote');
59
+ this.dom.classList.add(...getChangeClasses(this.node.attrs.dataTracked));
60
+ this.dom.appendChild(marker);
61
+ this.contentDOM && this.dom.appendChild(this.contentDOM);
62
+ this.dom.appendChild(deleteBtn);
63
+ };
64
+ this.handleMarkerClick = (e) => {
65
+ e.preventDefault();
66
+ e.stopPropagation();
67
+ const id = this.node.attrs.id;
68
+ const fn = getFootnotesElementState(this.view.state, id);
69
+ if (!fn) {
70
+ return;
71
+ }
72
+ for (const [node, pos] of fn.inlineFootnotes) {
73
+ if (node.attrs.rids.includes(id)) {
74
+ const tr = this.view.state.tr;
75
+ const selection = NodeSelection.create(this.view.state.doc, pos);
76
+ tr.setSelection(selection);
77
+ tr.scrollIntoView();
78
+ this.view.dispatch(tr);
79
+ }
80
+ }
81
+ };
82
+ this.handleDeleteClick = (e) => {
83
+ e.preventDefault();
84
+ e.stopPropagation();
85
+ const componentProps = {
86
+ header: 'Delete footnote',
87
+ message: 'This action will entirely remove the footnote from the list because it will no longer be used.',
88
+ handleDelete: this.handleDelete,
89
+ };
90
+ this.dialog = ReactSubView(this.props, DeleteFootnoteDialog, componentProps, this.node, this.getPos, this.view);
91
+ this.props.popper.show(this.dom, this.dialog, 'auto', false);
92
+ };
93
+ this.handleDelete = () => {
94
+ const tr = this.view.state.tr;
95
+ this.deleteInlineFootnotes(tr);
96
+ this.deleteFootnote(tr);
97
+ this.view.dispatch(tr);
98
+ };
99
+ this.deleteInlineFootnotes = (tr) => {
100
+ const id = this.node.attrs.id;
101
+ const fns = getFootnotesElementState(this.view.state, this.node.attrs.id);
102
+ fns === null || fns === void 0 ? void 0 : fns.inlineFootnotes.forEach(([node, pos]) => {
103
+ pos = tr.mapping.map(pos);
104
+ const rids = node.attrs.rids.filter((rid) => rid !== id);
105
+ if (isEqual(rids, node.attrs.rids)) {
106
+ return;
107
+ }
108
+ if (!rids.length) {
109
+ tr.delete(pos, pos + node.nodeSize);
110
+ }
111
+ else {
112
+ tr.setNodeAttribute(pos, 'rids', rids);
113
+ }
114
+ });
115
+ };
116
+ this.deleteFootnote = (tr) => {
117
+ const pos = tr.mapping.map(this.getPos());
118
+ const $pos = tr.doc.resolve(pos);
119
+ const element = findParentNodeOfTypeClosestToPos($pos, schema.nodes.footnotes_element);
120
+ if (element && getEffectiveChildCount(element.node) <= 1) {
121
+ tr.delete(element.pos, element.pos + element.node.nodeSize);
122
+ }
123
+ else {
124
+ tr.delete(pos, pos + this.node.nodeSize);
125
+ }
126
+ };
23
127
  }
24
128
  }
25
- export const setTCClasses = (node, dom) => {
26
- const dataTracked = node.attrs.dataTracked;
27
- if (dataTracked === null || dataTracked === void 0 ? void 0 : dataTracked.length) {
28
- const lastChange = dataTracked[dataTracked.length - 1];
29
- const changeClasses = getChangeClasses([lastChange]);
30
- dom.classList.add(...changeClasses);
129
+ const getEffectiveChildCount = (node) => {
130
+ let count = 0;
131
+ for (let i = 0; i < node.childCount; i++) {
132
+ const child = node.child(i);
133
+ if (!isDeleted(child)) {
134
+ count++;
135
+ }
31
136
  }
32
- dom.setAttribute('id', node.attrs.id);
137
+ return count;
33
138
  };
34
- export default createNodeOrElementView(FootnoteView, 'div', setTCClasses);
139
+ export default createNodeView(FootnoteView);
@@ -13,13 +13,16 @@
13
13
  * See the License for the specific language governing permissions and
14
14
  * limitations under the License.
15
15
  */
16
+ import { getChangeClasses } from '../lib/track-changes-utils';
16
17
  import BlockView from './block_view';
17
18
  import { createNodeOrElementView } from './creators';
18
- import { setTCClasses } from './footnote';
19
19
  export class FootnotesElementView extends BlockView {
20
20
  constructor() {
21
21
  super(...arguments);
22
22
  this.elementType = 'div';
23
+ this.updateClasses = () => {
24
+ updateClasses(this.node, this.dom);
25
+ };
23
26
  this.checkEditability = () => {
24
27
  var _a, _b;
25
28
  const editable = this.props.getCapabilities().editArticle && this.node.childCount
@@ -33,4 +36,9 @@ export class FootnotesElementView extends BlockView {
33
36
  this.checkEditability();
34
37
  }
35
38
  }
36
- export default createNodeOrElementView(FootnotesElementView, 'div', setTCClasses);
39
+ const updateClasses = (node, dom) => {
40
+ !node.childCount && dom.classList.add('empty-node');
41
+ dom.classList.add('footnotes-element');
42
+ dom.classList.add(...getChangeClasses(node.attrs.dataTracked));
43
+ };
44
+ export default createNodeOrElementView(FootnotesElementView, 'div', updateClasses);
@@ -0,0 +1,76 @@
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 { schema } from '@manuscripts/transform';
17
+ import { findChildrenByType, findParentNodeOfTypeClosestToPos, } from 'prosemirror-utils';
18
+ import { DeleteFootnoteDialog, } from '../components/views/DeleteFootnoteDialog';
19
+ import { deleteIcon } from '../icons';
20
+ import { getChangeClasses, isDeleted } from '../lib/track-changes-utils';
21
+ import { BaseNodeView } from './base_node_view';
22
+ import { createNodeView } from './creators';
23
+ import ReactSubView from './ReactSubView';
24
+ export class GeneralTableFootnoteView extends BaseNodeView {
25
+ constructor() {
26
+ super(...arguments);
27
+ this.initialise = () => {
28
+ this.dom = document.createElement('div');
29
+ this.contentDOM = document.createElement('div');
30
+ this.contentDOM.classList.add('footnote-text');
31
+ this.updateContents();
32
+ };
33
+ this.updateContents = () => {
34
+ const deleteBtn = document.createElement('span');
35
+ deleteBtn.classList.add('delete-icon');
36
+ deleteBtn.innerHTML = deleteIcon;
37
+ deleteBtn.addEventListener('mousedown', (e) => this.handleClick(e));
38
+ this.dom.innerHTML = '';
39
+ this.dom.classList.value = '';
40
+ this.dom.classList.add('footnote', 'general-table-footnote');
41
+ this.dom.classList.add(...getChangeClasses(this.node.attrs.dataTracked));
42
+ this.contentDOM && this.dom.appendChild(this.contentDOM);
43
+ this.dom.appendChild(deleteBtn);
44
+ };
45
+ this.handleClick = (e) => {
46
+ e.preventDefault();
47
+ e.stopPropagation();
48
+ const componentProps = {
49
+ header: 'Delete table general note',
50
+ message: 'This action will entirely remove the table general note.',
51
+ handleDelete: this.handleDelete,
52
+ };
53
+ this.dialog = ReactSubView(this.props, DeleteFootnoteDialog, componentProps, this.node, this.getPos, this.view);
54
+ this.props.popper.show(this.dom, this.dialog, 'auto', false);
55
+ };
56
+ this.handleDelete = () => {
57
+ const tr = this.view.state.tr;
58
+ const pos = this.getPos();
59
+ const $pos = this.view.state.doc.resolve(pos);
60
+ const footer = findParentNodeOfTypeClosestToPos($pos, schema.nodes.table_element_footer);
61
+ const element = findChildrenByType(footer.node, schema.nodes.footnotes_element)[0];
62
+ if (element && !isDeleted(element.node)) {
63
+ const from = pos;
64
+ const to = from + this.node.nodeSize;
65
+ tr.delete(from, to);
66
+ }
67
+ else {
68
+ const from = footer.pos;
69
+ const to = from + footer.node.nodeSize;
70
+ tr.delete(from, to);
71
+ }
72
+ this.view.dispatch(tr);
73
+ };
74
+ }
75
+ }
76
+ export default createNodeView(GeneralTableFootnoteView);
@@ -14,21 +14,17 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { ContextMenu } from '@manuscripts/style-guide';
17
- import { schema, } from '@manuscripts/transform';
18
- import { NodeSelection, TextSelection } from 'prosemirror-state';
19
- import { findChildrenByType, findParentNodeClosestToPos, } from 'prosemirror-utils';
20
- import { createFootnote, insertFootnote, insertTableFootnote, } from '../commands';
21
- import { FootnotesSelector } from '../components/views/FootnotesSelector';
22
- import { buildTableFootnoteLabels } from '../lib/footnotes';
17
+ import { isTableElementNode, } from '@manuscripts/transform';
18
+ import { TextSelection } from 'prosemirror-state';
19
+ import { FootnotesSelector, } from '../components/views/FootnotesSelector';
20
+ import { createFootnote, findFootnotesContainerNode, getFootnotesElementState, } from '../lib/footnotes';
23
21
  import { getChangeClasses, isDeleted, isPendingInsert, } from '../lib/track-changes-utils';
24
- import { footnotesKey } from '../plugins/footnotes';
25
22
  import { BaseNodeView } from './base_node_view';
26
23
  import { createNodeView } from './creators';
27
24
  import ReactSubView from './ReactSubView';
28
25
  export class InlineFootnoteView extends BaseNodeView {
29
26
  constructor() {
30
27
  super(...arguments);
31
- this.findParentTableElement = () => findParentNodeClosestToPos(this.view.state.doc.resolve(this.getPos()), (node) => node.type === schema.nodes.table_element);
32
28
  this.showContextMenu = () => {
33
29
  this.props.popper.destroy();
34
30
  const componentProps = {
@@ -37,7 +33,7 @@ export class InlineFootnoteView extends BaseNodeView {
37
33
  label: 'Edit',
38
34
  action: () => {
39
35
  this.props.popper.destroy();
40
- this.activateGenericFnModal();
36
+ this.showFootnotesSelector();
41
37
  },
42
38
  icon: 'Edit',
43
39
  },
@@ -46,93 +42,66 @@ export class InlineFootnoteView extends BaseNodeView {
46
42
  this.props.popper.show(this.dom, ReactSubView(this.props, ContextMenu, componentProps, this.node, this.getPos, this.view, 'context-menu'), 'right-start', false);
47
43
  };
48
44
  this.handleClick = () => {
49
- if (isDeleted(this.node)) {
45
+ if (isDeleted(this.node) || !this.props.getCapabilities().editArticle) {
50
46
  return;
51
47
  }
52
- const tableElement = this.findParentTableElement();
53
- if (tableElement) {
54
- this.activateModal({
55
- notes: this.getNotes(tableElement),
56
- onAdd: this.onAdd,
57
- });
48
+ if (this.isTableFootnote) {
49
+ this.showFootnotesSelector();
58
50
  }
59
51
  else {
60
52
  this.showContextMenu();
61
53
  }
62
54
  };
63
- this.scrollToReferenced = () => {
64
- var _a;
65
- if ((_a = this.node.attrs.rids) === null || _a === void 0 ? void 0 : _a.length) {
66
- let nodePos = undefined;
67
- this.view.state.doc.descendants((node, pos) => {
68
- if (node.attrs.id === this.node.attrs.rids[0]) {
69
- nodePos = pos;
70
- }
71
- });
72
- if (nodePos && this.props.dispatch) {
73
- const sel = TextSelection.near(this.view.state.doc.resolve(nodePos + 1));
74
- this.props.dispatch(this.view.state.tr.setSelection(sel).scrollIntoView());
75
- }
76
- }
77
- };
78
- this.activateGenericFnModal = () => {
55
+ this.showFootnotesSelector = () => {
79
56
  if (!this.props.getCapabilities().editArticle) {
80
57
  return;
81
58
  }
82
- const fnState = footnotesKey.getState(this.view.state);
83
- if (fnState) {
84
- this.activateModal({
85
- notes: Array.from(fnState.unusedFootnotes.values()).reduce((acc, n) => {
86
- const node = n[0];
87
- if (!isDeleted(node)) {
88
- acc.push({
89
- node,
90
- });
91
- }
92
- return acc;
93
- }, []),
94
- onCancel: () => {
95
- const { tr } = this.view.state;
96
- if (this.node.attrs.rids.length) {
97
- this.view.dispatch(tr.delete(this.getPos(), this.getPos() + this.node.nodeSize));
98
- }
99
- this.destroy();
100
- },
101
- onAdd: () => {
102
- const footnote = createFootnote(this.view.state, 'footnote');
103
- const tr = insertFootnote(this.view.state, this.view.state.tr, footnote);
104
- tr.setNodeAttribute(tr.mapping.map(this.getPos()), 'rids', [
105
- footnote.attrs.id,
106
- ]);
107
- this.view.dispatch(tr);
108
- this.view.focus();
109
- this.destroy();
110
- },
111
- addNewLabel: 'Replace with new footnote',
112
- });
113
- return true;
59
+ const state = this.view.state;
60
+ const pos = this.getPos();
61
+ const container = findFootnotesContainerNode(state.doc, pos);
62
+ const fn = getFootnotesElementState(state, container.node.attrs.id);
63
+ if (!fn) {
64
+ return [];
114
65
  }
115
- return false;
66
+ const rids = this.node.attrs.rids;
67
+ const footnotes = fn.footnotes
68
+ .map((n) => n[0])
69
+ .filter((n) => fn.unusedFootnoteIDs.has(n.attrs.id) || rids.includes(n.attrs.id));
70
+ const props = {
71
+ footnotes,
72
+ inlineFootnote: this.node,
73
+ labels: fn.labels,
74
+ onCancel: this.handleCancel,
75
+ onAdd: this.handleAdd,
76
+ onInsert: this.handleInsert,
77
+ };
78
+ this.popperContainer = ReactSubView(this.props, FootnotesSelector, props, this.node, this.getPos, this.view, 'footnote-editor');
79
+ this.props.popper.show(this.dom, this.popperContainer, 'auto', false);
116
80
  };
117
81
  this.updateContents = () => {
118
- const attrs = this.node.attrs;
119
- this.dom.setAttribute('rids', attrs.rids.join(','));
120
- this.dom.setAttribute('contents', attrs.contents);
121
82
  this.dom.className = [
122
- 'footnote',
83
+ 'footnote-marker',
123
84
  ...getChangeClasses(this.node.attrs.dataTracked),
124
85
  ].join(' ');
125
- if (this.isSelected() &&
126
- (!attrs.rids || !attrs.rids.length) &&
127
- !this.findParentTableElement()) {
128
- this.activateGenericFnModal();
86
+ const state = this.view.state;
87
+ const fn = getFootnotesElementState(state, this.node.attrs.id);
88
+ if (!fn) {
89
+ return;
129
90
  }
91
+ this.dom.innerText = fn.labels.get(this.node.attrs.id) || '';
130
92
  };
131
93
  this.initialise = () => {
132
94
  this.dom = this.createDOM();
133
- this.dom.classList.add('footnote');
95
+ this.dom.classList.add('footnote-marker');
134
96
  this.dom.addEventListener('click', this.handleClick);
135
97
  this.updateContents();
98
+ const container = findFootnotesContainerNode(this.view.state.doc, this.getPos());
99
+ this.isTableFootnote = isTableElementNode(container.node);
100
+ };
101
+ this.selectNode = () => {
102
+ if (!this.node.attrs.rids.length) {
103
+ this.showFootnotesSelector();
104
+ }
136
105
  };
137
106
  this.ignoreMutation = () => true;
138
107
  this.createDOM = () => {
@@ -143,71 +112,52 @@ export class InlineFootnoteView extends BaseNodeView {
143
112
  this.props.popper.destroy();
144
113
  (_a = this.popperContainer) === null || _a === void 0 ? void 0 : _a.remove();
145
114
  };
146
- this.getNotes = (tableElement) => {
147
- var _a;
148
- const footnotesElement = (_a = findChildrenByType(tableElement.node, schema.nodes.footnotes_element).pop()) === null || _a === void 0 ? void 0 : _a.node;
149
- let footnotes = [];
150
- if (footnotesElement) {
151
- const tablesFootnoteLabels = buildTableFootnoteLabels(tableElement.node);
152
- footnotes = findChildrenByType(footnotesElement, schema.nodes.footnote)
153
- .filter(({ node }) => !isDeleted(node))
154
- .map(({ node }) => ({
155
- node: node,
156
- index: tablesFootnoteLabels.get(node.attrs.id),
157
- }));
115
+ this.handleCancel = () => {
116
+ const tr = this.view.state.tr;
117
+ const rids = this.node.attrs.rids;
118
+ if (!rids.length) {
119
+ const pos = this.getPos();
120
+ tr.delete(pos, pos + this.node.nodeSize);
121
+ this.view.dispatch(tr);
158
122
  }
159
- return footnotes;
123
+ this.destroy();
160
124
  };
161
- this.onAdd = () => {
162
- const tableElement = this.findParentTableElement();
163
- if (tableElement) {
164
- insertTableFootnote(tableElement.node, tableElement.pos, this.view, {
165
- node: this.node,
166
- pos: this.getPos(),
167
- });
168
- this.destroy();
125
+ this.handleAdd = () => {
126
+ const state = this.view.state;
127
+ const pos = this.getPos();
128
+ const container = findFootnotesContainerNode(state.doc, pos);
129
+ const fn = getFootnotesElementState(state, container.node.attrs.id);
130
+ if (!fn) {
131
+ return;
169
132
  }
133
+ const tr = this.view.state.tr;
134
+ const footnote = createFootnote();
135
+ const rids = this.node.attrs.rids;
136
+ tr.setNodeAttribute(pos, 'rids', [...rids, footnote.attrs.id]);
137
+ const fnPos = fn.element[1] + fn.element[0].nodeSize - 1;
138
+ tr.insert(fnPos, footnote);
139
+ const selection = TextSelection.create(tr.doc, fnPos + 2);
140
+ tr.setSelection(selection).scrollIntoView();
141
+ this.view.dispatch(tr);
142
+ this.view.focus();
143
+ this.destroy();
170
144
  };
171
- this.onInsert = (notes) => {
172
- if (notes.length) {
173
- const contents = this.node.attrs.contents
174
- .split(',')
175
- .map((n) => parseInt(n));
176
- const rids = notes.map((note) => note.node.attrs.id);
177
- const { tr } = this.view.state;
145
+ this.handleInsert = (footnotes) => {
146
+ if (footnotes.length) {
147
+ const pos = this.getPos();
148
+ const rids = footnotes.map((note) => note.attrs.id);
149
+ const tr = this.view.state.tr;
178
150
  if (rids.length) {
179
- this.view.dispatch(tr.setNodeMarkup(this.getPos(), undefined, {
180
- rids,
181
- contents: notes
182
- .map(({ index }) => (index ? index : Math.max(...contents) + 1))
183
- .join(),
184
- }));
151
+ tr.setNodeAttribute(pos, 'rids', rids);
152
+ this.view.dispatch(tr);
185
153
  }
186
154
  else if (isPendingInsert(this.node)) {
187
- this.view.dispatch(tr.delete(this.getPos(), this.getPos() + this.node.nodeSize));
155
+ tr.delete(pos, pos + this.node.nodeSize);
156
+ this.view.dispatch(tr);
188
157
  }
189
158
  }
190
159
  this.destroy();
191
160
  };
192
161
  }
193
- isSelected() {
194
- const sel = this.view.state.selection;
195
- const juxtaposed = sel.$head.pos === sel.$anchor.pos &&
196
- sel.$head.pos === this.getPos() + this.node.nodeSize;
197
- if ((sel instanceof NodeSelection && sel.node == this.node) || juxtaposed) {
198
- return true;
199
- }
200
- return false;
201
- }
202
- activateModal(modalProps) {
203
- const defaultModal = {
204
- notes: [],
205
- onInsert: this.onInsert,
206
- onCancel: this.destroy,
207
- inlineFootnote: this.node,
208
- };
209
- this.popperContainer = ReactSubView(Object.assign(Object.assign({}, this.props), { dispatch: this.view.dispatch }), FootnotesSelector, Object.assign(Object.assign({}, defaultModal), modalProps), this.node, this.getPos, this.view, 'footnote-editor');
210
- this.props.popper.show(this.dom, this.popperContainer, 'auto', false);
211
- }
212
162
  }
213
163
  export default createNodeView(InlineFootnoteView);
@@ -14,8 +14,8 @@
14
14
  * limitations under the License.
15
15
  */
16
16
  import { BaseNodeView } from './base_node_view';
17
- import { createNodeView } from './creators';
18
- export class TableElementFooterView extends BaseNodeView {
17
+ import { createEditableNodeView } from './creators';
18
+ class TableElementFooterView extends BaseNodeView {
19
19
  constructor() {
20
20
  super(...arguments);
21
21
  this.initialise = () => {
@@ -25,9 +25,8 @@ export class TableElementFooterView extends BaseNodeView {
25
25
  this.dom = document.createElement('div');
26
26
  this.dom.classList.add('table-footer');
27
27
  this.dom.setAttribute('id', this.node.attrs.id);
28
- this.contentDOM = document.createElement('div');
29
- this.dom.appendChild(this.contentDOM);
28
+ this.contentDOM = this.dom;
30
29
  };
31
30
  }
32
31
  }
33
- export default createNodeView(TableElementFooterView);
32
+ export default createEditableNodeView(TableElementFooterView);