@atlaskit/editor-plugin-synced-block 3.5.1 → 3.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +17 -0
- package/dist/cjs/nodeviews/bodiedLazySyncedBlock.js +26 -0
- package/dist/cjs/nodeviews/bodiedSyncedBlock.js +87 -0
- package/dist/cjs/nodeviews/syncedBlock.js +8 -115
- package/dist/cjs/pm-plugins/actions.js +48 -40
- package/dist/cjs/pm-plugins/main.js +8 -2
- package/dist/cjs/pm-plugins/utils/track-sync-blocks.js +8 -0
- package/dist/cjs/pm-plugins/utils/utils.js +12 -2
- package/dist/cjs/syncedBlockPlugin.js +3 -0
- package/dist/cjs/ui/BodiedSyncBlockWrapper.js +25 -0
- package/dist/cjs/ui/CreateSyncedBlockDropdownItem.js +15 -2
- package/dist/cjs/ui/SyncBlockLabel.js +3 -2
- package/dist/cjs/ui/floating-toolbar.js +5 -3
- package/dist/es2019/nodeviews/bodiedLazySyncedBlock.js +16 -0
- package/dist/es2019/nodeviews/bodiedSyncedBlock.js +62 -0
- package/dist/es2019/nodeviews/syncedBlock.js +7 -96
- package/dist/es2019/pm-plugins/actions.js +56 -46
- package/dist/es2019/pm-plugins/main.js +8 -2
- package/dist/es2019/pm-plugins/utils/track-sync-blocks.js +8 -0
- package/dist/es2019/pm-plugins/utils/utils.js +11 -1
- package/dist/es2019/syncedBlockPlugin.js +4 -1
- package/dist/es2019/ui/BodiedSyncBlockWrapper.js +19 -0
- package/dist/es2019/ui/CreateSyncedBlockDropdownItem.js +16 -2
- package/dist/es2019/ui/SyncBlockLabel.js +3 -2
- package/dist/es2019/ui/floating-toolbar.js +12 -4
- package/dist/esm/nodeviews/bodiedLazySyncedBlock.js +15 -0
- package/dist/esm/nodeviews/bodiedSyncedBlock.js +80 -0
- package/dist/esm/nodeviews/syncedBlock.js +9 -116
- package/dist/esm/pm-plugins/actions.js +47 -39
- package/dist/esm/pm-plugins/main.js +8 -2
- package/dist/esm/pm-plugins/utils/track-sync-blocks.js +8 -0
- package/dist/esm/pm-plugins/utils/utils.js +11 -1
- package/dist/esm/syncedBlockPlugin.js +4 -1
- package/dist/esm/ui/BodiedSyncBlockWrapper.js +18 -0
- package/dist/esm/ui/CreateSyncedBlockDropdownItem.js +15 -2
- package/dist/esm/ui/SyncBlockLabel.js +3 -2
- package/dist/esm/ui/floating-toolbar.js +6 -4
- package/dist/types/nodeviews/bodiedLazySyncedBlock.d.ts +3 -0
- package/dist/types/nodeviews/bodiedSyncedBlock.d.ts +25 -0
- package/dist/types/nodeviews/syncedBlock.d.ts +1 -20
- package/dist/types/pm-plugins/utils/utils.d.ts +6 -2
- package/dist/types/syncedBlockPluginType.d.ts +2 -0
- package/dist/types/ui/BodiedSyncBlockWrapper.d.ts +9 -0
- package/dist/types-ts4.5/nodeviews/bodiedLazySyncedBlock.d.ts +3 -0
- package/dist/types-ts4.5/nodeviews/bodiedSyncedBlock.d.ts +25 -0
- package/dist/types-ts4.5/nodeviews/syncedBlock.d.ts +1 -20
- package/dist/types-ts4.5/pm-plugins/utils/utils.d.ts +6 -2
- package/dist/types-ts4.5/syncedBlockPluginType.d.ts +2 -0
- package/dist/types-ts4.5/ui/BodiedSyncBlockWrapper.d.ts +9 -0
- package/package.json +6 -6
- package/dist/cjs/ui/SyncBlockEditorWrapper.js +0 -45
- package/dist/es2019/ui/SyncBlockEditorWrapper.js +0 -29
- package/dist/esm/ui/SyncBlockEditorWrapper.js +0 -36
- package/dist/types/ui/SyncBlockEditorWrapper.d.ts +0 -16
- package/dist/types-ts4.5/ui/SyncBlockEditorWrapper.d.ts +0 -16
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ReactNodeView from '@atlaskit/editor-common/react-node-view';
|
|
3
|
+
import { BodiedSyncBlockSharedCssClassName } from '@atlaskit/editor-common/sync-block';
|
|
4
|
+
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
5
|
+
import { BodiedSyncBlockWrapper } from '../ui/BodiedSyncBlockWrapper';
|
|
6
|
+
const toDOM = () => ['div', {
|
|
7
|
+
class: BodiedSyncBlockSharedCssClassName.content,
|
|
8
|
+
contenteditable: true
|
|
9
|
+
}, 0];
|
|
10
|
+
class BodiedSyncBlock extends ReactNodeView {
|
|
11
|
+
constructor(props) {
|
|
12
|
+
super(props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props);
|
|
13
|
+
this.pluginOptions = props.pluginOptions;
|
|
14
|
+
}
|
|
15
|
+
createDomRef() {
|
|
16
|
+
const domRef = document.createElement('div');
|
|
17
|
+
domRef.classList.add(BodiedSyncBlockSharedCssClassName.prefix);
|
|
18
|
+
return domRef;
|
|
19
|
+
}
|
|
20
|
+
render(_props, forwardRef) {
|
|
21
|
+
var _this$pluginOptions;
|
|
22
|
+
return /*#__PURE__*/React.createElement(BodiedSyncBlockWrapper, {
|
|
23
|
+
ref: forwardRef,
|
|
24
|
+
dataProvider: (_this$pluginOptions = this.pluginOptions) === null || _this$pluginOptions === void 0 ? void 0 : _this$pluginOptions.dataProvider,
|
|
25
|
+
node: this.node
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
getContentDOM() {
|
|
29
|
+
const {
|
|
30
|
+
dom,
|
|
31
|
+
contentDOM
|
|
32
|
+
} = DOMSerializer.renderSpec(document, toDOM());
|
|
33
|
+
if (dom instanceof HTMLElement) {
|
|
34
|
+
return {
|
|
35
|
+
dom,
|
|
36
|
+
contentDOM
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
export const bodiedSyncBlockNodeView = ({
|
|
43
|
+
pluginOptions,
|
|
44
|
+
pmPluginFactoryParams,
|
|
45
|
+
api,
|
|
46
|
+
syncBlockStore
|
|
47
|
+
}) => (node, view, getPos) => {
|
|
48
|
+
const {
|
|
49
|
+
portalProviderAPI,
|
|
50
|
+
eventDispatcher
|
|
51
|
+
} = pmPluginFactoryParams;
|
|
52
|
+
return new BodiedSyncBlock({
|
|
53
|
+
api,
|
|
54
|
+
pluginOptions,
|
|
55
|
+
node,
|
|
56
|
+
view,
|
|
57
|
+
getPos,
|
|
58
|
+
portalProviderAPI,
|
|
59
|
+
eventDispatcher,
|
|
60
|
+
syncBlockStore
|
|
61
|
+
}).init();
|
|
62
|
+
};
|
|
@@ -1,21 +1,8 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import ReactNodeView from '@atlaskit/editor-common/react-node-view';
|
|
3
3
|
import { SyncBlockSharedCssClassName } from '@atlaskit/editor-common/sync-block';
|
|
4
|
-
import {
|
|
5
|
-
import { convertSyncBlockPMNodeToSyncBlockData, useFetchDocNode, useHandleContentChanges } from '@atlaskit/editor-synced-block-provider';
|
|
6
|
-
import { SyncBlockEditorWrapper, SyncBlockEditorWrapperDataId } from '../ui/SyncBlockEditorWrapper';
|
|
4
|
+
import { useFetchDocNode } from '@atlaskit/editor-synced-block-provider';
|
|
7
5
|
import { SyncBlockRendererWrapper } from '../ui/SyncBlockRendererWrapper';
|
|
8
|
-
const defaultSyncBlockEditorDocument = {
|
|
9
|
-
version: 1,
|
|
10
|
-
type: 'doc',
|
|
11
|
-
content: [{
|
|
12
|
-
type: 'paragraph',
|
|
13
|
-
content: [{
|
|
14
|
-
type: 'text',
|
|
15
|
-
text: 'This is a source sync block. Edit me to update the content.'
|
|
16
|
-
}]
|
|
17
|
-
}]
|
|
18
|
-
};
|
|
19
6
|
const defaultSyncBlockRendererDocument = {
|
|
20
7
|
version: 1,
|
|
21
8
|
type: 'doc',
|
|
@@ -39,47 +26,9 @@ class SyncBlock extends ReactNodeView {
|
|
|
39
26
|
domRef.classList.add(SyncBlockSharedCssClassName.prefix);
|
|
40
27
|
return domRef;
|
|
41
28
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
setInnerEditorView(editorView) {
|
|
46
|
-
var _this$options, _this$options$dataPro;
|
|
47
|
-
// set inner editor view
|
|
48
|
-
this.syncBlockStore.setSyncBlockNestedEditorView(editorView);
|
|
49
|
-
const nodes = [convertSyncBlockPMNodeToSyncBlockData(this.node, false)];
|
|
50
|
-
(_this$options = this.options) === null || _this$options === void 0 ? void 0 : (_this$options$dataPro = _this$options.dataProvider) === null || _this$options$dataPro === void 0 ? void 0 : _this$options$dataPro.fetchNodesData(nodes).then(data => {
|
|
51
|
-
var _data$;
|
|
52
|
-
const tr = editorView.state.tr;
|
|
53
|
-
if (data && (_data$ = data[0]) !== null && _data$ !== void 0 && _data$.content) {
|
|
54
|
-
const newNode = editorView.state.schema.nodeFromJSON(data[0].content);
|
|
55
|
-
editorView.dispatch(tr.replaceWith(0, editorView.state.doc.nodeSize - 2, newNode));
|
|
56
|
-
}
|
|
57
|
-
});
|
|
58
|
-
}
|
|
59
|
-
renderEditor() {
|
|
60
|
-
var _this$options2, _this$options4;
|
|
61
|
-
const fabricEditorPopupScrollParent = this.view.dom.closest('.fabric-editor-popup-scroll-parent');
|
|
62
|
-
if (!(fabricEditorPopupScrollParent instanceof HTMLElement)) {
|
|
63
|
-
return null;
|
|
64
|
-
}
|
|
65
|
-
if (!((_this$options2 = this.options) !== null && _this$options2 !== void 0 && _this$options2.getSyncedBlockEditor)) {
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
return /*#__PURE__*/React.createElement(SyncBlockEditorWrapper, {
|
|
69
|
-
popupsBoundariesElement: fabricEditorPopupScrollParent,
|
|
70
|
-
popupsMountPoint: fabricEditorPopupScrollParent,
|
|
71
|
-
defaultDocument: defaultSyncBlockEditorDocument,
|
|
72
|
-
useHandleContentChanges: updatedDoc => {
|
|
73
|
-
var _this$options3;
|
|
74
|
-
return useHandleContentChanges(updatedDoc, this.isSource(), this.node, (_this$options3 = this.options) === null || _this$options3 === void 0 ? void 0 : _this$options3.dataProvider);
|
|
75
|
-
},
|
|
76
|
-
setInnerEditorView: editorView => this.setInnerEditorView(editorView),
|
|
77
|
-
getSyncedBlockEditor: (_this$options4 = this.options) === null || _this$options4 === void 0 ? void 0 : _this$options4.getSyncedBlockEditor
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
renderRenderer() {
|
|
81
|
-
var _this$options5, _this$options7;
|
|
82
|
-
if (!((_this$options5 = this.options) !== null && _this$options5 !== void 0 && _this$options5.getSyncedBlockRenderer)) {
|
|
29
|
+
render() {
|
|
30
|
+
var _this$options, _this$options3;
|
|
31
|
+
if (!((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.getSyncedBlockRenderer)) {
|
|
83
32
|
return null;
|
|
84
33
|
}
|
|
85
34
|
|
|
@@ -87,58 +36,20 @@ class SyncBlock extends ReactNodeView {
|
|
|
87
36
|
|
|
88
37
|
return /*#__PURE__*/React.createElement(SyncBlockRendererWrapper, {
|
|
89
38
|
useFetchDocNode: () => {
|
|
90
|
-
var _this$
|
|
91
|
-
return useFetchDocNode(this.view, this.node, defaultSyncBlockRendererDocument, (_this$
|
|
39
|
+
var _this$options2;
|
|
40
|
+
return useFetchDocNode(this.view, this.node, defaultSyncBlockRendererDocument, (_this$options2 = this.options) === null || _this$options2 === void 0 ? void 0 : _this$options2.dataProvider);
|
|
92
41
|
},
|
|
93
|
-
getSyncedBlockRenderer: (_this$
|
|
42
|
+
getSyncedBlockRenderer: (_this$options3 = this.options) === null || _this$options3 === void 0 ? void 0 : _this$options3.getSyncedBlockRenderer
|
|
94
43
|
});
|
|
95
44
|
}
|
|
96
|
-
render() {
|
|
97
|
-
if (this.isSource()) {
|
|
98
|
-
return this.renderEditor();
|
|
99
|
-
}
|
|
100
|
-
return this.renderRenderer();
|
|
101
|
-
}
|
|
102
|
-
stopEvent(event) {
|
|
103
|
-
var _target$closest;
|
|
104
|
-
const target = event.target;
|
|
105
|
-
if (!target) {
|
|
106
|
-
return false;
|
|
107
|
-
}
|
|
108
|
-
const isInNestedEditor = ((_target$closest = target.closest) === null || _target$closest === void 0 ? void 0 : _target$closest.call(target, `[data-testid="${SyncBlockEditorWrapperDataId}"]`)) != null;
|
|
109
|
-
if (isInNestedEditor) {
|
|
110
|
-
this.selectNode();
|
|
111
|
-
return true;
|
|
112
|
-
}
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
|
-
selectNode() {
|
|
116
|
-
this.selectSyncBlockNode(undefined);
|
|
117
|
-
}
|
|
118
45
|
destroy() {
|
|
119
46
|
var _this$unsubscribe;
|
|
120
47
|
if (this.fetchIntervalId) {
|
|
121
48
|
window.clearInterval(this.fetchIntervalId);
|
|
122
49
|
}
|
|
123
|
-
this.syncBlockStore.setSyncBlockNestedEditorView(undefined);
|
|
124
50
|
(_this$unsubscribe = this.unsubscribe) === null || _this$unsubscribe === void 0 ? void 0 : _this$unsubscribe.call(this);
|
|
125
51
|
super.destroy();
|
|
126
52
|
}
|
|
127
|
-
selectSyncBlockNode(relativeSelectionPos) {
|
|
128
|
-
var _this$reactComponentP, _this$reactComponentP2;
|
|
129
|
-
const getPos = typeof this.getPos === 'function' ? this.getPos() : 0;
|
|
130
|
-
const selectionAPI = (_this$reactComponentP = this.reactComponentProps.api) === null || _this$reactComponentP === void 0 ? void 0 : (_this$reactComponentP2 = _this$reactComponentP.selection) === null || _this$reactComponentP2 === void 0 ? void 0 : _this$reactComponentP2.actions;
|
|
131
|
-
if (!selectionAPI) {
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
const tr = selectionAPI.selectNearNode({
|
|
135
|
-
selectionRelativeToNode: relativeSelectionPos,
|
|
136
|
-
selection: NodeSelection.create(this.view.state.doc, getPos !== null && getPos !== void 0 ? getPos : 0)
|
|
137
|
-
})(this.view.state);
|
|
138
|
-
if (tr) {
|
|
139
|
-
this.view.dispatch(tr);
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
53
|
}
|
|
143
54
|
export const syncBlockNodeView = ({
|
|
144
55
|
options,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE
|
|
2
|
-
import {
|
|
3
|
-
import { canBeConvertedToSyncBlock, findSyncBlock } from './utils/utils';
|
|
1
|
+
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
2
|
+
import { copyDomNode, toDOM } from '@atlaskit/editor-common/copy-button';
|
|
3
|
+
import { canBeConvertedToSyncBlock, findSyncBlock, findSyncBlockOrBodiedSyncBlock, isBodiedSyncBlockNode } from './utils/utils';
|
|
4
4
|
export const createSyncedBlock = ({
|
|
5
5
|
tr,
|
|
6
6
|
syncBlockStore,
|
|
@@ -9,69 +9,79 @@ export const createSyncedBlock = ({
|
|
|
9
9
|
const {
|
|
10
10
|
schema: {
|
|
11
11
|
nodes: {
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
bodiedSyncBlock,
|
|
13
|
+
paragraph
|
|
14
14
|
}
|
|
15
15
|
}
|
|
16
16
|
} = tr.doc.type;
|
|
17
|
-
const syncBlockNode = syncBlockStore.createSyncBlockNode();
|
|
18
|
-
const node = syncBlock.createAndFill({
|
|
19
|
-
...syncBlockNode.attrs
|
|
20
|
-
});
|
|
21
|
-
if (!node) {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
17
|
|
|
25
18
|
// If the selection is empty, we want to insert the sync block on a new line
|
|
26
19
|
if (tr.selection.empty) {
|
|
20
|
+
const storeSyncBlockNode = syncBlockStore.createSyncBlockNode();
|
|
21
|
+
const paragraphNode = paragraph.createAndFill({});
|
|
22
|
+
const newBodiedSyncBlockNode = bodiedSyncBlock.createAndFill({
|
|
23
|
+
...storeSyncBlockNode.attrs
|
|
24
|
+
}, paragraphNode ? [paragraphNode] : []);
|
|
25
|
+
if (!newBodiedSyncBlockNode) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
27
28
|
if (typeAheadInsert) {
|
|
28
|
-
tr = typeAheadInsert(
|
|
29
|
+
tr = typeAheadInsert(newBodiedSyncBlockNode);
|
|
29
30
|
} else {
|
|
30
|
-
tr = tr.replaceSelectionWith(
|
|
31
|
+
tr = tr.replaceSelectionWith(newBodiedSyncBlockNode).scrollIntoView();
|
|
31
32
|
}
|
|
32
33
|
} else {
|
|
33
34
|
const conversionInfo = canBeConvertedToSyncBlock(tr.selection);
|
|
34
|
-
if (conversionInfo) {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
// TMP solution to wait for the nested editor view to be set
|
|
39
|
-
// this will be removed once we have a proper architecture settled
|
|
40
|
-
setTimeout(() => {
|
|
41
|
-
const editorView = syncBlockStore.getSyncBlockNestedEditorView();
|
|
42
|
-
if (editorView) {
|
|
43
|
-
const innerTr = editorView.state.tr;
|
|
44
|
-
const innerNode = editorView.state.schema.nodeFromJSON(innerNodeJson);
|
|
45
|
-
editorView.dispatch(innerTr.replaceWith(0, editorView.state.doc.nodeSize - 2, innerNode));
|
|
46
|
-
}
|
|
47
|
-
}, 1000);
|
|
35
|
+
if (!conversionInfo) {
|
|
36
|
+
// TODO: EDITOR-1665 - Raise an error analytics event
|
|
37
|
+
return false;
|
|
48
38
|
} else {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
39
|
+
const storeSyncBlockNode = syncBlockStore.createSyncBlockNode();
|
|
40
|
+
const newBodiedSyncBlockNode = bodiedSyncBlock.createAndFill({
|
|
41
|
+
...storeSyncBlockNode.attrs
|
|
42
|
+
}, conversionInfo.contentToInclude);
|
|
43
|
+
if (!newBodiedSyncBlockNode) {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
tr.replaceWith(conversionInfo.from - 1, conversionInfo.to, newBodiedSyncBlockNode).scrollIntoView();
|
|
52
47
|
}
|
|
53
48
|
}
|
|
54
49
|
return tr;
|
|
55
50
|
};
|
|
56
|
-
export const copySyncedBlockReferenceToClipboard = api => (state,
|
|
57
|
-
if (!(api !== null && api !== void 0 && api.floatingToolbar)
|
|
51
|
+
export const copySyncedBlockReferenceToClipboard = api => (state, _dispatch, _view) => {
|
|
52
|
+
if (!(api !== null && api !== void 0 && api.floatingToolbar)) {
|
|
58
53
|
return false;
|
|
59
54
|
}
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
55
|
+
const syncBlockFindResult = findSyncBlockOrBodiedSyncBlock(state);
|
|
56
|
+
if (!syncBlockFindResult) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
const isBodiedSyncBlock = isBodiedSyncBlockNode(syncBlockFindResult.node, state.schema.nodes.bodiedSyncBlock);
|
|
60
|
+
let referenceSyncBlockNode = null;
|
|
61
|
+
if (isBodiedSyncBlock) {
|
|
62
|
+
const {
|
|
63
|
+
schema: {
|
|
64
|
+
nodes: {
|
|
65
|
+
syncBlock
|
|
66
|
+
}
|
|
64
67
|
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
68
|
+
} = state.tr.doc.type;
|
|
69
|
+
|
|
70
|
+
// create sync block reference node
|
|
71
|
+
referenceSyncBlockNode = syncBlock.createAndFill({
|
|
72
|
+
resourceId: syncBlockFindResult.node.attrs.resourceId
|
|
73
|
+
});
|
|
74
|
+
if (!referenceSyncBlockNode) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
} else {
|
|
78
|
+
referenceSyncBlockNode = syncBlockFindResult.node;
|
|
79
|
+
}
|
|
80
|
+
if (!referenceSyncBlockNode) {
|
|
72
81
|
return false;
|
|
73
82
|
}
|
|
74
|
-
|
|
83
|
+
const domNode = toDOM(referenceSyncBlockNode, state.tr.doc.type.schema);
|
|
84
|
+
copyDomNode(domNode, referenceSyncBlockNode.type, state.tr.selection);
|
|
75
85
|
return true;
|
|
76
86
|
};
|
|
77
87
|
export const editSyncedBlockSource = (syncBlockStore, api) => (state, dispatch, _view) => {
|
|
@@ -112,7 +122,7 @@ export const removeSyncedBlock = api => (state, dispatch, _view) => {
|
|
|
112
122
|
},
|
|
113
123
|
tr
|
|
114
124
|
} = state;
|
|
115
|
-
const syncBlock =
|
|
125
|
+
const syncBlock = findSyncBlockOrBodiedSyncBlock(state);
|
|
116
126
|
if (!syncBlock) {
|
|
117
127
|
return false;
|
|
118
128
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
|
|
2
2
|
import { PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
3
|
+
import { lazyBodiedSyncBlockView } from '../nodeviews/bodiedLazySyncedBlock';
|
|
3
4
|
import { lazySyncBlockView } from '../nodeviews/lazySyncedBlock';
|
|
4
5
|
import { trackSyncBlocks } from './utils/track-sync-blocks';
|
|
5
6
|
export const syncedBlockPluginKey = new PluginKey('syncedBlockPlugin');
|
|
@@ -28,6 +29,12 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
|
|
|
28
29
|
pmPluginFactoryParams,
|
|
29
30
|
api,
|
|
30
31
|
syncBlockStore
|
|
32
|
+
}),
|
|
33
|
+
bodiedSyncBlock: lazyBodiedSyncBlockView({
|
|
34
|
+
pluginOptions: options,
|
|
35
|
+
pmPluginFactoryParams,
|
|
36
|
+
api,
|
|
37
|
+
syncBlockStore
|
|
31
38
|
})
|
|
32
39
|
}
|
|
33
40
|
},
|
|
@@ -36,7 +43,6 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
|
|
|
36
43
|
return {
|
|
37
44
|
destroy() {
|
|
38
45
|
syncBlockStore.setEditorView(undefined);
|
|
39
|
-
syncBlockStore.setSyncBlockNestedEditorView(undefined);
|
|
40
46
|
}
|
|
41
47
|
};
|
|
42
48
|
},
|
|
@@ -61,7 +67,7 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
|
|
|
61
67
|
}
|
|
62
68
|
return true;
|
|
63
69
|
},
|
|
64
|
-
appendTransaction: (trs,
|
|
70
|
+
appendTransaction: (trs, _oldState, newState) => {
|
|
65
71
|
trs.filter(tr => tr.docChanged).forEach(tr => {
|
|
66
72
|
syncBlockStore === null || syncBlockStore === void 0 ? void 0 : syncBlockStore.rebaseTransaction(tr, newState);
|
|
67
73
|
});
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
2
2
|
export const trackSyncBlocks = (storeManager, tr, state) => {
|
|
3
|
+
// TODO: EDITOR-2430 - Disable tracking for now, it will be updated to handle the new bodied sync block
|
|
4
|
+
const dontTrack = true;
|
|
5
|
+
if (dontTrack) {
|
|
6
|
+
return {
|
|
7
|
+
removed: [],
|
|
8
|
+
added: []
|
|
9
|
+
};
|
|
10
|
+
}
|
|
3
11
|
const sourceSyncBlockRemoved = {};
|
|
4
12
|
const sourceSyncBlockAdded = {};
|
|
5
13
|
|
|
@@ -6,8 +6,18 @@ export const findSyncBlock = (state, selection) => {
|
|
|
6
6
|
const {
|
|
7
7
|
syncBlock
|
|
8
8
|
} = state.schema.nodes;
|
|
9
|
-
return findSelectedNodeOfType(syncBlock)(selection || state.selection)
|
|
9
|
+
return findSelectedNodeOfType(syncBlock)(selection || state.selection);
|
|
10
10
|
};
|
|
11
|
+
export const findBodiedSyncBlock = (state, selection) => {
|
|
12
|
+
const {
|
|
13
|
+
bodiedSyncBlock
|
|
14
|
+
} = state.schema.nodes;
|
|
15
|
+
return findSelectedNodeOfType(bodiedSyncBlock)(selection || state.selection) || findParentNodeOfType(bodiedSyncBlock)(selection || state.selection);
|
|
16
|
+
};
|
|
17
|
+
export const findSyncBlockOrBodiedSyncBlock = (state, selection) => {
|
|
18
|
+
return findSyncBlock(state, selection) || findBodiedSyncBlock(state, selection);
|
|
19
|
+
};
|
|
20
|
+
export const isBodiedSyncBlockNode = (node, bodiedSyncBlock) => node.type === bodiedSyncBlock;
|
|
11
21
|
export const canBeConvertedToSyncBlock = selection => {
|
|
12
22
|
let from = selection.from;
|
|
13
23
|
let to = selection.to;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import { syncBlock } from '@atlaskit/adf-schema';
|
|
2
|
+
import { bodiedSyncBlock, syncBlock } from '@atlaskit/adf-schema';
|
|
3
3
|
import { blockTypeMessages } from '@atlaskit/editor-common/messages';
|
|
4
4
|
import { IconSyncBlock } from '@atlaskit/editor-common/quick-insert';
|
|
5
5
|
import { SyncBlockStoreManager } from '@atlaskit/editor-synced-block-provider';
|
|
@@ -21,6 +21,9 @@ export const syncedBlockPlugin = ({
|
|
|
21
21
|
return [{
|
|
22
22
|
name: 'syncBlock',
|
|
23
23
|
node: syncBlock
|
|
24
|
+
}, {
|
|
25
|
+
name: 'bodiedSyncBlock',
|
|
26
|
+
node: bodiedSyncBlock
|
|
24
27
|
}];
|
|
25
28
|
},
|
|
26
29
|
pmPlugins() {
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { useHandleContentChanges } from '@atlaskit/editor-synced-block-provider';
|
|
3
|
+
import { SyncBlockLabel } from './SyncBlockLabel';
|
|
4
|
+
export const BodiedSyncBlockWrapper = /*#__PURE__*/React.forwardRef(({
|
|
5
|
+
node,
|
|
6
|
+
dataProvider
|
|
7
|
+
}, ref) => {
|
|
8
|
+
// TODO: EDITOR-2429 - this should be debounced (either here or in the data provider) to avoid excessive API writes
|
|
9
|
+
const docJSON = {
|
|
10
|
+
version: 1,
|
|
11
|
+
type: 'doc',
|
|
12
|
+
content: node.content.toJSON()
|
|
13
|
+
};
|
|
14
|
+
useHandleContentChanges(docJSON, true, node, dataProvider);
|
|
15
|
+
return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(SyncBlockLabel, null), /*#__PURE__*/React.createElement("div", {
|
|
16
|
+
"data-testid": "bodied-sync-block-wrapper",
|
|
17
|
+
ref: ref
|
|
18
|
+
}));
|
|
19
|
+
});
|
|
@@ -16,8 +16,22 @@ export const CreateSyncedBlockDropdownItem = ({
|
|
|
16
16
|
return null;
|
|
17
17
|
}
|
|
18
18
|
const onClick = () => {
|
|
19
|
-
var _api$core;
|
|
20
|
-
api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(
|
|
19
|
+
var _api$core, _api$core2;
|
|
20
|
+
api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
|
|
21
|
+
tr
|
|
22
|
+
}) => {
|
|
23
|
+
var _api$blockControls, _api$blockControls$co;
|
|
24
|
+
api === null || api === void 0 ? void 0 : api.syncedBlock.commands.insertSyncedBlock()({
|
|
25
|
+
tr
|
|
26
|
+
});
|
|
27
|
+
api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : (_api$blockControls$co = _api$blockControls.commands) === null || _api$blockControls$co === void 0 ? void 0 : _api$blockControls$co.toggleBlockMenu({
|
|
28
|
+
closeMenu: true
|
|
29
|
+
})({
|
|
30
|
+
tr
|
|
31
|
+
});
|
|
32
|
+
return tr;
|
|
33
|
+
});
|
|
34
|
+
api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.focus();
|
|
21
35
|
};
|
|
22
36
|
return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
|
|
23
37
|
elemBefore: /*#__PURE__*/React.createElement(SyncBlocksIcon, {
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { useIntl } from 'react-intl-next';
|
|
3
3
|
import { syncBlockMessages as messages } from '@atlaskit/editor-common/messages';
|
|
4
|
+
import { SyncBlockLabelSharedCssClassName } from '@atlaskit/editor-common/sync-block';
|
|
4
5
|
const SyncBlockLabelDataId = 'sync-block-label';
|
|
5
6
|
const SyncBlockLabelComponent = () => {
|
|
6
7
|
const {
|
|
7
8
|
formatMessage
|
|
8
9
|
} = useIntl();
|
|
9
10
|
return /*#__PURE__*/React.createElement("div", {
|
|
10
|
-
"data-
|
|
11
|
+
"data-testid": SyncBlockLabelDataId
|
|
11
12
|
// eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
|
|
12
13
|
,
|
|
13
|
-
className:
|
|
14
|
+
className: SyncBlockLabelSharedCssClassName.labelClassName
|
|
14
15
|
}, formatMessage(messages.syncedBlockLabel));
|
|
15
16
|
};
|
|
16
17
|
export const SyncBlockLabel = /*#__PURE__*/React.memo(SyncBlockLabelComponent);
|
|
@@ -6,17 +6,25 @@ import CopyIcon from '@atlaskit/icon/core/copy';
|
|
|
6
6
|
import DeleteIcon from '@atlaskit/icon/core/delete';
|
|
7
7
|
import LinkExternalIcon from '@atlaskit/icon/core/link-external';
|
|
8
8
|
import { copySyncedBlockReferenceToClipboard, editSyncedBlockSource, removeSyncedBlock } from '../pm-plugins/actions';
|
|
9
|
-
import {
|
|
9
|
+
import { findSyncBlockOrBodiedSyncBlock, isBodiedSyncBlockNode } from '../pm-plugins/utils/utils';
|
|
10
10
|
export const getToolbarConfig = (state, intl, _options = {}, _providerFactory, api, syncBlockStore) => {
|
|
11
11
|
var _api$decorations;
|
|
12
|
-
const syncBlockObject =
|
|
12
|
+
const syncBlockObject = findSyncBlockOrBodiedSyncBlock(state);
|
|
13
13
|
if (!syncBlockObject) {
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
16
|
+
const {
|
|
17
|
+
schema: {
|
|
18
|
+
nodes: {
|
|
19
|
+
bodiedSyncBlock
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
} = state;
|
|
23
|
+
const isBodiedSyncBlock = isBodiedSyncBlockNode(syncBlockObject.node, bodiedSyncBlock);
|
|
16
24
|
const {
|
|
17
25
|
formatMessage
|
|
18
26
|
} = intl;
|
|
19
|
-
const nodeType =
|
|
27
|
+
const nodeType = syncBlockObject.node.type;
|
|
20
28
|
const hoverDecoration = api === null || api === void 0 ? void 0 : (_api$decorations = api.decorations) === null || _api$decorations === void 0 ? void 0 : _api$decorations.actions.hoverDecoration;
|
|
21
29
|
const hoverDecorationProps = (nodeType, className) => ({
|
|
22
30
|
onMouseEnter: hoverDecoration === null || hoverDecoration === void 0 ? void 0 : hoverDecoration(nodeType, true, className),
|
|
@@ -38,7 +46,7 @@ export const getToolbarConfig = (state, intl, _options = {}, _providerFactory, a
|
|
|
38
46
|
};
|
|
39
47
|
items.push(copyButton);
|
|
40
48
|
const disabled = !syncBlockStore.getSyncBlockURL(syncBlockObject.node.attrs.resourceId);
|
|
41
|
-
if (!
|
|
49
|
+
if (!isBodiedSyncBlock) {
|
|
42
50
|
const editSourceButton = {
|
|
43
51
|
id: 'editor.syncedBlock.editSource',
|
|
44
52
|
type: 'button',
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { withLazyLoading } from '@atlaskit/editor-common/lazy-node-view';
|
|
2
|
+
export var lazyBodiedSyncBlockView = function lazyBodiedSyncBlockView(props) {
|
|
3
|
+
return withLazyLoading({
|
|
4
|
+
nodeName: 'bodiedSyncBlock',
|
|
5
|
+
getNodeViewOptions: function getNodeViewOptions() {},
|
|
6
|
+
loader: function loader() {
|
|
7
|
+
var result = import( /* webpackChunkName: "@atlaskit-internal_editor-plugin-bodied-synced-block-nodeview" */
|
|
8
|
+
'./bodiedSyncedBlock').then(function (_ref) {
|
|
9
|
+
var bodiedSyncBlockNodeView = _ref.bodiedSyncBlockNodeView;
|
|
10
|
+
return bodiedSyncBlockNodeView(props);
|
|
11
|
+
});
|
|
12
|
+
return result;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import _classCallCheck from "@babel/runtime/helpers/classCallCheck";
|
|
2
|
+
import _createClass from "@babel/runtime/helpers/createClass";
|
|
3
|
+
import _possibleConstructorReturn from "@babel/runtime/helpers/possibleConstructorReturn";
|
|
4
|
+
import _getPrototypeOf from "@babel/runtime/helpers/getPrototypeOf";
|
|
5
|
+
import _inherits from "@babel/runtime/helpers/inherits";
|
|
6
|
+
function _callSuper(t, o, e) { return o = _getPrototypeOf(o), _possibleConstructorReturn(t, _isNativeReflectConstruct() ? Reflect.construct(o, e || [], _getPrototypeOf(t).constructor) : o.apply(t, e)); }
|
|
7
|
+
function _isNativeReflectConstruct() { try { var t = !Boolean.prototype.valueOf.call(Reflect.construct(Boolean, [], function () {})); } catch (t) {} return (_isNativeReflectConstruct = function _isNativeReflectConstruct() { return !!t; })(); }
|
|
8
|
+
import React from 'react';
|
|
9
|
+
import ReactNodeView from '@atlaskit/editor-common/react-node-view';
|
|
10
|
+
import { BodiedSyncBlockSharedCssClassName } from '@atlaskit/editor-common/sync-block';
|
|
11
|
+
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
12
|
+
import { BodiedSyncBlockWrapper } from '../ui/BodiedSyncBlockWrapper';
|
|
13
|
+
var toDOM = function toDOM() {
|
|
14
|
+
return ['div', {
|
|
15
|
+
class: BodiedSyncBlockSharedCssClassName.content,
|
|
16
|
+
contenteditable: true
|
|
17
|
+
}, 0];
|
|
18
|
+
};
|
|
19
|
+
var BodiedSyncBlock = /*#__PURE__*/function (_ReactNodeView) {
|
|
20
|
+
function BodiedSyncBlock(props) {
|
|
21
|
+
var _this;
|
|
22
|
+
_classCallCheck(this, BodiedSyncBlock);
|
|
23
|
+
_this = _callSuper(this, BodiedSyncBlock, [props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props]);
|
|
24
|
+
_this.pluginOptions = props.pluginOptions;
|
|
25
|
+
return _this;
|
|
26
|
+
}
|
|
27
|
+
_inherits(BodiedSyncBlock, _ReactNodeView);
|
|
28
|
+
return _createClass(BodiedSyncBlock, [{
|
|
29
|
+
key: "createDomRef",
|
|
30
|
+
value: function createDomRef() {
|
|
31
|
+
var domRef = document.createElement('div');
|
|
32
|
+
domRef.classList.add(BodiedSyncBlockSharedCssClassName.prefix);
|
|
33
|
+
return domRef;
|
|
34
|
+
}
|
|
35
|
+
}, {
|
|
36
|
+
key: "render",
|
|
37
|
+
value: function render(_props, forwardRef) {
|
|
38
|
+
var _this$pluginOptions;
|
|
39
|
+
return /*#__PURE__*/React.createElement(BodiedSyncBlockWrapper, {
|
|
40
|
+
ref: forwardRef,
|
|
41
|
+
dataProvider: (_this$pluginOptions = this.pluginOptions) === null || _this$pluginOptions === void 0 ? void 0 : _this$pluginOptions.dataProvider,
|
|
42
|
+
node: this.node
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
}, {
|
|
46
|
+
key: "getContentDOM",
|
|
47
|
+
value: function getContentDOM() {
|
|
48
|
+
var _DOMSerializer$render = DOMSerializer.renderSpec(document, toDOM()),
|
|
49
|
+
dom = _DOMSerializer$render.dom,
|
|
50
|
+
contentDOM = _DOMSerializer$render.contentDOM;
|
|
51
|
+
if (dom instanceof HTMLElement) {
|
|
52
|
+
return {
|
|
53
|
+
dom: dom,
|
|
54
|
+
contentDOM: contentDOM
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
}]);
|
|
60
|
+
}(ReactNodeView);
|
|
61
|
+
export var bodiedSyncBlockNodeView = function bodiedSyncBlockNodeView(_ref) {
|
|
62
|
+
var pluginOptions = _ref.pluginOptions,
|
|
63
|
+
pmPluginFactoryParams = _ref.pmPluginFactoryParams,
|
|
64
|
+
api = _ref.api,
|
|
65
|
+
syncBlockStore = _ref.syncBlockStore;
|
|
66
|
+
return function (node, view, getPos) {
|
|
67
|
+
var portalProviderAPI = pmPluginFactoryParams.portalProviderAPI,
|
|
68
|
+
eventDispatcher = pmPluginFactoryParams.eventDispatcher;
|
|
69
|
+
return new BodiedSyncBlock({
|
|
70
|
+
api: api,
|
|
71
|
+
pluginOptions: pluginOptions,
|
|
72
|
+
node: node,
|
|
73
|
+
view: view,
|
|
74
|
+
getPos: getPos,
|
|
75
|
+
portalProviderAPI: portalProviderAPI,
|
|
76
|
+
eventDispatcher: eventDispatcher,
|
|
77
|
+
syncBlockStore: syncBlockStore
|
|
78
|
+
}).init();
|
|
79
|
+
};
|
|
80
|
+
};
|