@atlaskit/editor-plugin-synced-block 2.0.1 → 2.1.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 +19 -0
- package/afm-cc/tsconfig.json +3 -0
- package/afm-dev-agents/tsconfig.json +3 -0
- package/afm-jira/tsconfig.json +3 -0
- package/afm-passionfruit/tsconfig.json +3 -0
- package/afm-post-office/tsconfig.json +3 -0
- package/afm-rovo-extension/tsconfig.json +3 -0
- package/afm-townsquare/tsconfig.json +3 -0
- package/dist/cjs/nodeviews/syncedBlock.js +118 -75
- package/dist/cjs/pm-plugins/actions.js +23 -9
- package/dist/cjs/pm-plugins/main.js +4 -3
- package/dist/cjs/pm-plugins/utils/utils.js +11 -0
- package/dist/cjs/syncedBlockPlugin.js +8 -3
- package/dist/cjs/ui/SyncBlockEditorWrapper.js +38 -0
- package/dist/cjs/ui/SyncBlockRendererWrapper.js +26 -0
- package/dist/cjs/ui/floating-toolbar.js +58 -3
- package/dist/es2019/nodeviews/syncedBlock.js +103 -67
- package/dist/es2019/pm-plugins/actions.js +23 -8
- package/dist/es2019/pm-plugins/main.js +4 -3
- package/dist/es2019/pm-plugins/utils/utils.js +7 -0
- package/dist/es2019/syncedBlockPlugin.js +38 -33
- package/dist/es2019/ui/SyncBlockEditorWrapper.js +28 -0
- package/dist/es2019/ui/SyncBlockRendererWrapper.js +20 -0
- package/dist/es2019/ui/floating-toolbar.js +56 -2
- package/dist/esm/nodeviews/syncedBlock.js +116 -72
- package/dist/esm/pm-plugins/actions.js +21 -8
- package/dist/esm/pm-plugins/main.js +4 -3
- package/dist/esm/pm-plugins/utils/utils.js +5 -0
- package/dist/esm/syncedBlockPlugin.js +8 -3
- package/dist/esm/ui/SyncBlockEditorWrapper.js +31 -0
- package/dist/esm/ui/SyncBlockRendererWrapper.js +19 -0
- package/dist/esm/ui/floating-toolbar.js +57 -3
- package/dist/types/nodeviews/syncedBlock.d.ts +29 -15
- package/dist/types/pm-plugins/actions.d.ts +3 -1
- package/dist/types/pm-plugins/main.d.ts +4 -3
- package/dist/types/pm-plugins/utils/utils.d.ts +3 -0
- package/dist/types/syncedBlockPluginType.d.ts +6 -2
- package/dist/types/ui/SyncBlockEditorWrapper.d.ts +16 -0
- package/dist/types/ui/SyncBlockRendererWrapper.d.ts +9 -0
- package/dist/types/ui/floating-toolbar.d.ts +6 -2
- package/dist/types-ts4.5/nodeviews/syncedBlock.d.ts +29 -15
- package/dist/types-ts4.5/pm-plugins/actions.d.ts +3 -1
- package/dist/types-ts4.5/pm-plugins/main.d.ts +4 -3
- package/dist/types-ts4.5/pm-plugins/utils/utils.d.ts +3 -0
- package/dist/types-ts4.5/syncedBlockPluginType.d.ts +8 -2
- package/dist/types-ts4.5/ui/SyncBlockEditorWrapper.d.ts +16 -0
- package/dist/types-ts4.5/ui/SyncBlockRendererWrapper.d.ts +9 -0
- package/dist/types-ts4.5/ui/floating-toolbar.d.ts +6 -2
- package/package.json +6 -4
|
@@ -1,105 +1,141 @@
|
|
|
1
|
-
|
|
2
|
-
import React, { useMemo, useRef, useState } from 'react';
|
|
1
|
+
import React from 'react';
|
|
3
2
|
import ReactNodeView from '@atlaskit/editor-common/react-node-view';
|
|
4
|
-
|
|
3
|
+
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
4
|
+
import { SyncBlockEditorWrapper, SyncBlockEditorWrapperDataId } from '../ui/SyncBlockEditorWrapper';
|
|
5
|
+
import { SyncBlockRendererWrapper } from '../ui/SyncBlockRendererWrapper';
|
|
6
|
+
const defaultSyncBlockEditorDocument = {
|
|
5
7
|
version: 1,
|
|
6
8
|
type: 'doc',
|
|
7
9
|
content: [{
|
|
8
10
|
type: 'paragraph',
|
|
9
11
|
content: [{
|
|
10
12
|
type: 'text',
|
|
11
|
-
text: 'This is a
|
|
13
|
+
text: 'This is a source sync block. Edit me to update the content.'
|
|
12
14
|
}]
|
|
13
15
|
}]
|
|
14
16
|
};
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const content = editorView.state.doc.toJSON().content;
|
|
26
|
-
const rendererDocument = {
|
|
27
|
-
version: 1,
|
|
28
|
-
type: 'doc',
|
|
29
|
-
content
|
|
30
|
-
};
|
|
31
|
-
setRendererDocument(rendererDocument);
|
|
32
|
-
};
|
|
33
|
-
const onEditorReady = ({
|
|
34
|
-
editorView
|
|
35
|
-
}) => {
|
|
36
|
-
innerEditorView.current = editorView || null;
|
|
37
|
-
};
|
|
38
|
-
const boundariesElement = useMemo(() => {
|
|
39
|
-
// eslint-disable-next-line @atlaskit/editor/no-as-casting
|
|
40
|
-
return dom.closest('.fabric-editor-popup-scroll-parent');
|
|
41
|
-
}, [dom]);
|
|
42
|
-
if (!boundariesElement || !(boundariesElement instanceof HTMLElement)) {
|
|
43
|
-
return null;
|
|
44
|
-
}
|
|
45
|
-
if (!(config !== null && config !== void 0 && config.getSyncedBlockEditor) || !(config !== null && config !== void 0 && config.getSyncedBlockRenderer)) {
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
return /*#__PURE__*/React.createElement("div", {
|
|
49
|
-
"data-testid": SyncBlockEditorWrapperDataId
|
|
50
|
-
}, config.getSyncedBlockEditor({
|
|
51
|
-
boundariesElement: boundariesElement,
|
|
52
|
-
defaultDocument: defaultSyncBlockDocument,
|
|
53
|
-
mountPoint: dom,
|
|
54
|
-
onChange: onChange,
|
|
55
|
-
onEditorReady: onEditorReady
|
|
56
|
-
}), /*#__PURE__*/React.createElement("div", {
|
|
57
|
-
style: {
|
|
58
|
-
width: '100%',
|
|
59
|
-
height: '1px',
|
|
60
|
-
// eslint-disable-next-line @atlaskit/design-system/ensure-design-token-usage
|
|
61
|
-
backgroundColor: 'purple'
|
|
62
|
-
}
|
|
63
|
-
}), config.getSyncedBlockRenderer({
|
|
64
|
-
docNode: rendererDocument
|
|
65
|
-
}));
|
|
17
|
+
const defaultSyncBlockRendererDocument = {
|
|
18
|
+
version: 1,
|
|
19
|
+
type: 'doc',
|
|
20
|
+
content: [{
|
|
21
|
+
type: 'paragraph',
|
|
22
|
+
content: [{
|
|
23
|
+
type: 'text',
|
|
24
|
+
text: 'This is a reference sync block. Stay tuned for updates...'
|
|
25
|
+
}]
|
|
26
|
+
}]
|
|
66
27
|
};
|
|
67
28
|
class SyncBlock extends ReactNodeView {
|
|
29
|
+
constructor(props) {
|
|
30
|
+
super(props.node, props.view, props.getPos, props.portalProviderAPI, props.eventDispatcher, props);
|
|
31
|
+
const {
|
|
32
|
+
resourceId,
|
|
33
|
+
localId
|
|
34
|
+
} = props.node.attrs;
|
|
35
|
+
// Temporary solution to identify the source
|
|
36
|
+
this.isSource = resourceId === localId;
|
|
37
|
+
this.options = props.options;
|
|
38
|
+
}
|
|
68
39
|
createDomRef() {
|
|
69
40
|
const domRef = document.createElement('div');
|
|
70
|
-
domRef.setAttribute('style', 'border: purple solid 1px;');
|
|
71
41
|
return domRef;
|
|
72
42
|
}
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
43
|
+
handleContentChanges(_updatedDoc) {
|
|
44
|
+
// write data
|
|
45
|
+
}
|
|
46
|
+
setInnerEditorView(_editorView) {
|
|
47
|
+
// set inner editor view
|
|
48
|
+
}
|
|
49
|
+
renderEditor() {
|
|
50
|
+
var _this$options, _this$options2;
|
|
51
|
+
const popupsBoundariesElement = this.dom.closest('.fabric-editor-popup-scroll-parent');
|
|
52
|
+
if (!(popupsBoundariesElement instanceof HTMLElement)) {
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
if (!((_this$options = this.options) !== null && _this$options !== void 0 && _this$options.getSyncedBlockEditor)) {
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
return /*#__PURE__*/React.createElement(SyncBlockEditorWrapper, {
|
|
59
|
+
popupsBoundariesElement: popupsBoundariesElement,
|
|
60
|
+
popupsMountPoint: this.dom,
|
|
61
|
+
defaultDocument: defaultSyncBlockEditorDocument,
|
|
62
|
+
handleContentChanges: this.handleContentChanges,
|
|
63
|
+
setInnerEditorView: this.setInnerEditorView,
|
|
64
|
+
getSyncedBlockEditor: (_this$options2 = this.options) === null || _this$options2 === void 0 ? void 0 : _this$options2.getSyncedBlockEditor
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
renderRenderer() {
|
|
68
|
+
var _this$options3, _this$options4;
|
|
69
|
+
if (!((_this$options3 = this.options) !== null && _this$options3 !== void 0 && _this$options3.getSyncedBlockRenderer)) {
|
|
70
|
+
return null;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// get document node from data provider
|
|
74
|
+
const docNode = defaultSyncBlockRendererDocument;
|
|
75
|
+
return /*#__PURE__*/React.createElement(SyncBlockRendererWrapper, {
|
|
76
|
+
docNode: docNode,
|
|
77
|
+
getSyncedBlockRenderer: (_this$options4 = this.options) === null || _this$options4 === void 0 ? void 0 : _this$options4.getSyncedBlockRenderer
|
|
77
78
|
});
|
|
78
79
|
}
|
|
80
|
+
render() {
|
|
81
|
+
if (this.isSource) {
|
|
82
|
+
return this.renderEditor();
|
|
83
|
+
}
|
|
84
|
+
return this.renderRenderer();
|
|
85
|
+
}
|
|
79
86
|
stopEvent(event) {
|
|
80
87
|
var _target$closest;
|
|
81
88
|
const target = event.target;
|
|
82
89
|
if (!target) {
|
|
83
90
|
return false;
|
|
84
91
|
}
|
|
85
|
-
|
|
92
|
+
const isInNestedEditor = ((_target$closest = target.closest) === null || _target$closest === void 0 ? void 0 : _target$closest.call(target, `[data-testid="${SyncBlockEditorWrapperDataId}"]`)) != null;
|
|
93
|
+
if (isInNestedEditor) {
|
|
94
|
+
this.selectNode();
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
selectNode() {
|
|
100
|
+
this.selectSyncBlockNode(undefined);
|
|
86
101
|
}
|
|
87
102
|
destroy() {
|
|
88
103
|
var _this$unsubscribe;
|
|
89
104
|
(_this$unsubscribe = this.unsubscribe) === null || _this$unsubscribe === void 0 ? void 0 : _this$unsubscribe.call(this);
|
|
90
105
|
super.destroy();
|
|
91
106
|
}
|
|
107
|
+
selectSyncBlockNode(relativeSelectionPos) {
|
|
108
|
+
var _this$reactComponentP, _this$reactComponentP2;
|
|
109
|
+
const getPos = typeof this.getPos === 'function' ? this.getPos() : 0;
|
|
110
|
+
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;
|
|
111
|
+
if (!selectionAPI) {
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const tr = selectionAPI.selectNearNode({
|
|
115
|
+
selectionRelativeToNode: relativeSelectionPos,
|
|
116
|
+
selection: NodeSelection.create(this.view.state.doc, getPos !== null && getPos !== void 0 ? getPos : 0)
|
|
117
|
+
})(this.view.state);
|
|
118
|
+
if (tr) {
|
|
119
|
+
this.view.dispatch(tr);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
92
122
|
}
|
|
93
123
|
export const syncBlockNodeView = ({
|
|
94
|
-
|
|
95
|
-
pmPluginFactoryParams
|
|
124
|
+
options,
|
|
125
|
+
pmPluginFactoryParams,
|
|
126
|
+
api
|
|
96
127
|
}) => (node, view, getPos) => {
|
|
97
128
|
const {
|
|
98
129
|
portalProviderAPI,
|
|
99
130
|
eventDispatcher
|
|
100
131
|
} = pmPluginFactoryParams;
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
132
|
+
return new SyncBlock({
|
|
133
|
+
api,
|
|
134
|
+
options,
|
|
135
|
+
node,
|
|
136
|
+
view,
|
|
137
|
+
getPos,
|
|
138
|
+
portalProviderAPI,
|
|
139
|
+
eventDispatcher
|
|
140
|
+
}).init();
|
|
105
141
|
};
|
|
@@ -1,19 +1,34 @@
|
|
|
1
|
+
import uuid from 'uuid';
|
|
2
|
+
import { toDOM, copyDomNode } from '@atlaskit/editor-common/copy-button';
|
|
3
|
+
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
1
4
|
import { safeInsert } from '@atlaskit/editor-prosemirror/utils';
|
|
2
|
-
const getRandomId = () => {
|
|
3
|
-
if (!globalThis.crypto || typeof globalThis.crypto.randomUUID !== 'function') {
|
|
4
|
-
return new Date().toISOString();
|
|
5
|
-
}
|
|
6
|
-
return globalThis.crypto.randomUUID();
|
|
7
|
-
};
|
|
8
5
|
export const createSyncedBlock = state => {
|
|
6
|
+
const id = uuid();
|
|
9
7
|
const tr = state.tr;
|
|
10
8
|
// const { breakout } = state.schema.marks;
|
|
11
9
|
const node = state.schema.nodes.syncBlock.createChecked({
|
|
12
|
-
resourceId:
|
|
13
|
-
localId:
|
|
10
|
+
resourceId: id,
|
|
11
|
+
localId: id
|
|
14
12
|
}, null
|
|
15
13
|
// [breakout.create({ mode: 'wide' })],
|
|
16
14
|
);
|
|
17
15
|
safeInsert(node)(tr);
|
|
18
16
|
return tr;
|
|
17
|
+
};
|
|
18
|
+
export const copySyncedBlockReferenceToClipboard = (state, _dispatch, _view) => {
|
|
19
|
+
const {
|
|
20
|
+
schema,
|
|
21
|
+
selection
|
|
22
|
+
} = state;
|
|
23
|
+
if (selection instanceof NodeSelection) {
|
|
24
|
+
const nodeType = selection.node.type;
|
|
25
|
+
const domNode = toDOM(selection.node, schema);
|
|
26
|
+
// clear local-id
|
|
27
|
+
if (domNode instanceof HTMLElement) {
|
|
28
|
+
domNode.setAttribute('data-local-id', '');
|
|
29
|
+
}
|
|
30
|
+
copyDomNode(domNode, nodeType, selection);
|
|
31
|
+
return true;
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
19
34
|
};
|
|
@@ -5,7 +5,7 @@ export const syncedBlockPluginKey = new PluginKey('syncedBlockPlugin');
|
|
|
5
5
|
|
|
6
6
|
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
7
7
|
|
|
8
|
-
export const createPlugin = (
|
|
8
|
+
export const createPlugin = (options, pmPluginFactoryParams, _syncBlockStore, api) => {
|
|
9
9
|
return new SafePlugin({
|
|
10
10
|
key: syncedBlockPluginKey,
|
|
11
11
|
state: {
|
|
@@ -23,8 +23,9 @@ export const createPlugin = (config, pmPluginFactoryParams) => {
|
|
|
23
23
|
props: {
|
|
24
24
|
nodeViews: {
|
|
25
25
|
syncBlock: lazySyncBlockView({
|
|
26
|
-
|
|
27
|
-
pmPluginFactoryParams
|
|
26
|
+
options,
|
|
27
|
+
pmPluginFactoryParams,
|
|
28
|
+
api
|
|
28
29
|
})
|
|
29
30
|
}
|
|
30
31
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { findParentNodeOfType, findSelectedNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
2
|
+
export const findSyncBlock = (state, selection) => {
|
|
3
|
+
const {
|
|
4
|
+
syncBlock
|
|
5
|
+
} = state.schema.nodes;
|
|
6
|
+
return findSelectedNodeOfType(syncBlock)(selection || state.selection) || findParentNodeOfType(syncBlock)(selection || state.selection);
|
|
7
|
+
};
|
|
@@ -1,40 +1,45 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { syncBlock } from '@atlaskit/adf-schema';
|
|
3
|
+
import { SyncBlockStoreManager } from '@atlaskit/editor-common/sync-block';
|
|
3
4
|
import SmartLinkIcon from '@atlaskit/icon/core/smart-link';
|
|
4
5
|
import { createSyncedBlock } from './pm-plugins/actions';
|
|
5
6
|
import { createPlugin } from './pm-plugins/main';
|
|
6
7
|
import { getToolbarConfig } from './ui/floating-toolbar';
|
|
7
8
|
export const syncedBlockPlugin = ({
|
|
8
|
-
config
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
9
|
+
config,
|
|
10
|
+
api
|
|
11
|
+
}) => {
|
|
12
|
+
const syncBlockStore = new SyncBlockStoreManager(config === null || config === void 0 ? void 0 : config.dataProvider);
|
|
13
|
+
return {
|
|
14
|
+
name: 'syncedBlock',
|
|
15
|
+
nodes() {
|
|
16
|
+
return [{
|
|
17
|
+
name: 'syncBlock',
|
|
18
|
+
node: syncBlock
|
|
19
|
+
}];
|
|
20
|
+
},
|
|
21
|
+
pmPlugins() {
|
|
22
|
+
return [{
|
|
23
|
+
name: 'syncedBlockPlugin',
|
|
24
|
+
plugin: params => createPlugin(config, params, syncBlockStore, api)
|
|
25
|
+
}];
|
|
26
|
+
},
|
|
27
|
+
pluginsOptions: {
|
|
28
|
+
quickInsert: () => [{
|
|
29
|
+
id: 'syncBlock',
|
|
30
|
+
title: 'Synced Block',
|
|
31
|
+
description: 'Create a synced block',
|
|
32
|
+
priority: 800,
|
|
33
|
+
keywords: ['synced', 'block', 'synced-block', 'sync', 'sync-block'],
|
|
34
|
+
keyshortcut: '',
|
|
35
|
+
icon: () => /*#__PURE__*/React.createElement(SmartLinkIcon, {
|
|
36
|
+
label: "Synced Block"
|
|
37
|
+
}),
|
|
38
|
+
action: (_insert, state) => {
|
|
39
|
+
return createSyncedBlock(state);
|
|
40
|
+
}
|
|
41
|
+
}],
|
|
42
|
+
floatingToolbar: (state, intl, providerFactory) => getToolbarConfig(state, intl, config, providerFactory)
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export const SyncBlockEditorWrapperDataId = 'sync-block-plugin-editor-wrapper';
|
|
3
|
+
const SyncBlockEditorWrapperComponent = ({
|
|
4
|
+
defaultDocument,
|
|
5
|
+
getSyncedBlockEditor,
|
|
6
|
+
popupsBoundariesElement,
|
|
7
|
+
popupsMountPoint,
|
|
8
|
+
setInnerEditorView,
|
|
9
|
+
handleContentChanges
|
|
10
|
+
}) => {
|
|
11
|
+
return (
|
|
12
|
+
/*#__PURE__*/
|
|
13
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop, @atlaskit/design-system/ensure-design-token-usage
|
|
14
|
+
React.createElement("div", {
|
|
15
|
+
"data-testid": SyncBlockEditorWrapperDataId,
|
|
16
|
+
style: {
|
|
17
|
+
border: 'purple solid 1px'
|
|
18
|
+
}
|
|
19
|
+
}, getSyncedBlockEditor({
|
|
20
|
+
popupsBoundariesElement,
|
|
21
|
+
defaultDocument,
|
|
22
|
+
popupsMountPoint,
|
|
23
|
+
onChange: value => handleContentChanges(value.state.doc),
|
|
24
|
+
onEditorReady: value => setInnerEditorView(value.editorView)
|
|
25
|
+
}))
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
export const SyncBlockEditorWrapper = /*#__PURE__*/React.memo(SyncBlockEditorWrapperComponent);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
const SyncBlockRendererWrapperDataId = 'sync-block-plugin-renderer-wrapper';
|
|
3
|
+
const SyncBlockRendererWrapperComponent = ({
|
|
4
|
+
getSyncedBlockRenderer,
|
|
5
|
+
docNode
|
|
6
|
+
}) => {
|
|
7
|
+
return (
|
|
8
|
+
/*#__PURE__*/
|
|
9
|
+
// eslint-disable-next-line @atlaskit/ui-styling-standard/enforce-style-prop, @atlaskit/design-system/ensure-design-token-usage
|
|
10
|
+
React.createElement("div", {
|
|
11
|
+
"data-testid": SyncBlockRendererWrapperDataId,
|
|
12
|
+
style: {
|
|
13
|
+
border: 'blue solid 1px'
|
|
14
|
+
}
|
|
15
|
+
}, getSyncedBlockRenderer({
|
|
16
|
+
docNode
|
|
17
|
+
}))
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
export const SyncBlockRendererWrapper = /*#__PURE__*/React.memo(SyncBlockRendererWrapperComponent);
|
|
@@ -1,3 +1,57 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import { findDomRefAtPos } from '@atlaskit/editor-prosemirror/utils';
|
|
2
|
+
import CopyIcon from '@atlaskit/icon/core/copy';
|
|
3
|
+
import LinkExternalIcon from '@atlaskit/icon/core/link-external';
|
|
4
|
+
import { copySyncedBlockReferenceToClipboard } from '../pm-plugins/actions';
|
|
5
|
+
import { findSyncBlock } from '../pm-plugins/utils/utils';
|
|
6
|
+
export const getToolbarConfig = (state, _intl, _options = {}, _providerFactory) => {
|
|
7
|
+
const syncBlockObject = findSyncBlock(state);
|
|
8
|
+
if (!syncBlockObject) {
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
const nodeType = state.schema.nodes.syncBlock;
|
|
12
|
+
const items = [];
|
|
13
|
+
const copyButton = {
|
|
14
|
+
id: 'editor.syncedBlock.copy',
|
|
15
|
+
type: 'button',
|
|
16
|
+
appearance: 'subtle',
|
|
17
|
+
icon: CopyIcon,
|
|
18
|
+
title: 'Copy',
|
|
19
|
+
showTitle: true,
|
|
20
|
+
tooltipContent: 'Copy reference to clipboard',
|
|
21
|
+
onClick: copySyncedBlockReferenceToClipboard
|
|
22
|
+
};
|
|
23
|
+
items.push(copyButton);
|
|
24
|
+
if (syncBlockObject.node.attrs.resourceId !== syncBlockObject.node.attrs.localId) {
|
|
25
|
+
const editSourceButton = {
|
|
26
|
+
id: 'editor.syncedBlock.editSource',
|
|
27
|
+
type: 'button',
|
|
28
|
+
appearance: 'subtle',
|
|
29
|
+
icon: LinkExternalIcon,
|
|
30
|
+
title: 'Edit source',
|
|
31
|
+
showTitle: true,
|
|
32
|
+
tooltipContent: 'Navigate to source page of the sync block',
|
|
33
|
+
disabled: true,
|
|
34
|
+
onClick: (_state, _dispatch, view) => {
|
|
35
|
+
if (!view) {
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
// to be implemented in a follow up PR
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
items.push(editSourceButton);
|
|
43
|
+
}
|
|
44
|
+
const getDomRef = editorView => {
|
|
45
|
+
const domAtPos = editorView.domAtPos.bind(editorView);
|
|
46
|
+
const element = findDomRefAtPos(syncBlockObject.pos, domAtPos);
|
|
47
|
+
return element;
|
|
48
|
+
};
|
|
49
|
+
return {
|
|
50
|
+
title: 'Synced Block floating controls',
|
|
51
|
+
getDomRef,
|
|
52
|
+
nodeType,
|
|
53
|
+
items,
|
|
54
|
+
scrollable: true,
|
|
55
|
+
groupLabel: 'Synced blocks'
|
|
56
|
+
};
|
|
3
57
|
};
|