@atlaskit/editor-plugin-synced-block 4.2.1 → 4.2.3
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 +16 -0
- package/dist/cjs/editor-commands/index.js +39 -30
- package/dist/cjs/pm-plugins/utils/utils.js +43 -27
- package/dist/cjs/syncedBlockPlugin.js +3 -0
- package/dist/cjs/ui/CreateSyncedBlockDropdownItem.js +63 -8
- package/dist/cjs/ui/block-menu-components.js +1 -1
- package/dist/cjs/ui/floating-toolbar.js +2 -2
- package/dist/es2019/editor-commands/index.js +24 -14
- package/dist/es2019/pm-plugins/utils/utils.js +43 -29
- package/dist/es2019/syncedBlockPlugin.js +2 -1
- package/dist/es2019/ui/CreateSyncedBlockDropdownItem.js +63 -7
- package/dist/es2019/ui/block-menu-components.js +2 -2
- package/dist/es2019/ui/floating-toolbar.js +2 -2
- package/dist/esm/editor-commands/index.js +38 -29
- package/dist/esm/pm-plugins/utils/utils.js +43 -27
- package/dist/esm/syncedBlockPlugin.js +4 -1
- package/dist/esm/ui/CreateSyncedBlockDropdownItem.js +60 -7
- package/dist/esm/ui/block-menu-components.js +2 -2
- package/dist/esm/ui/floating-toolbar.js +2 -2
- package/dist/types/editor-commands/index.d.ts +3 -2
- package/dist/types/pm-plugins/utils/utils.d.ts +13 -5
- package/dist/types/syncedBlockPluginType.d.ts +1 -0
- package/dist/types/ui/CreateSyncedBlockDropdownItem.d.ts +2 -2
- package/dist/types-ts4.5/editor-commands/index.d.ts +3 -2
- package/dist/types-ts4.5/pm-plugins/utils/utils.d.ts +13 -5
- package/dist/types-ts4.5/syncedBlockPluginType.d.ts +1 -0
- package/dist/types-ts4.5/ui/CreateSyncedBlockDropdownItem.d.ts +2 -2
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @atlaskit/editor-plugin-synced-block
|
|
2
2
|
|
|
3
|
+
## 4.2.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`9aaeaa5054b55`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/9aaeaa5054b55) -
|
|
8
|
+
EDITOR-2863 Add copy sync block option to block menu
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
|
|
11
|
+
## 4.2.2
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [`3432c4a4a074c`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/3432c4a4a074c) -
|
|
16
|
+
[ux] EDITOR-2525 update block menu convert to sync block to support all fishfooding node types
|
|
17
|
+
- Updated dependencies
|
|
18
|
+
|
|
3
19
|
## 4.2.1
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -3,9 +3,10 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.removeSyncedBlock = exports.editSyncedBlockSource = exports.createSyncedBlock = exports.copySyncedBlockReferenceToClipboard = void 0;
|
|
6
|
+
exports.removeSyncedBlock = exports.editSyncedBlockSource = exports.createSyncedBlock = exports.copySyncedBlockReferenceToClipboardEditorCommand = exports.copySyncedBlockReferenceToClipboard = void 0;
|
|
7
7
|
var _analytics = require("@atlaskit/editor-common/analytics");
|
|
8
8
|
var _copyButton = require("@atlaskit/editor-common/copy-button");
|
|
9
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
9
10
|
var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
10
11
|
var _utils2 = require("../pm-plugins/utils/utils");
|
|
11
12
|
var createSyncedBlock = exports.createSyncedBlock = function createSyncedBlock(_ref) {
|
|
@@ -48,49 +49,57 @@ var createSyncedBlock = exports.createSyncedBlock = function createSyncedBlock(_
|
|
|
48
49
|
// Save the new node with empty content to backend
|
|
49
50
|
// This is so that the node can be copied and referenced without the source being saved/published
|
|
50
51
|
syncBlockStore.createBodiedSyncBlockNode(_attrs);
|
|
51
|
-
tr.replaceWith(conversionInfo.from - 1, conversionInfo.to, _newBodiedSyncBlockNode).scrollIntoView();
|
|
52
|
+
tr.replaceWith(conversionInfo.from > 0 ? conversionInfo.from - 1 : 0, conversionInfo.to, _newBodiedSyncBlockNode).scrollIntoView();
|
|
53
|
+
|
|
54
|
+
// set selection to the end of the previous selection + 1 for the position taken up by the start of the new synced block
|
|
55
|
+
tr.setSelection(_state.TextSelection.create(tr.doc, conversionInfo.to + 1));
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
// This transaction will be intercepted in filterTransaction and dispatched when saving to backend succeeds
|
|
55
59
|
// see filterTransaction for more details
|
|
56
60
|
return tr;
|
|
57
61
|
};
|
|
58
|
-
var
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
62
|
+
var copySyncedBlockReferenceToClipboardEditorCommand = exports.copySyncedBlockReferenceToClipboardEditorCommand = function copySyncedBlockReferenceToClipboardEditorCommand(_ref2) {
|
|
63
|
+
var tr = _ref2.tr;
|
|
64
|
+
if (copySyncedBlockReferenceToClipboardInternal(tr.doc.type.schema, tr.selection)) {
|
|
65
|
+
return tr;
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
};
|
|
69
|
+
var copySyncedBlockReferenceToClipboard = exports.copySyncedBlockReferenceToClipboard = function copySyncedBlockReferenceToClipboard(state, _dispatch, _view) {
|
|
70
|
+
return copySyncedBlockReferenceToClipboardInternal(state.tr.doc.type.schema, state.tr.selection);
|
|
71
|
+
};
|
|
72
|
+
var copySyncedBlockReferenceToClipboardInternal = function copySyncedBlockReferenceToClipboardInternal(schema, selection) {
|
|
73
|
+
var syncBlockFindResult = (0, _utils2.findSyncBlockOrBodiedSyncBlock)(schema, selection);
|
|
74
|
+
if (!syncBlockFindResult) {
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
var isBodiedSyncBlock = (0, _utils2.isBodiedSyncBlockNode)(syncBlockFindResult.node, schema.nodes.bodiedSyncBlock);
|
|
78
|
+
var referenceSyncBlockNode = null;
|
|
79
|
+
if (isBodiedSyncBlock) {
|
|
80
|
+
var syncBlock = schema.nodes.syncBlock;
|
|
71
81
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
if (!referenceSyncBlockNode) {
|
|
77
|
-
return false;
|
|
78
|
-
}
|
|
79
|
-
} else {
|
|
80
|
-
referenceSyncBlockNode = syncBlockFindResult.node;
|
|
81
|
-
}
|
|
82
|
+
// create sync block reference node
|
|
83
|
+
referenceSyncBlockNode = syncBlock.createAndFill({
|
|
84
|
+
resourceId: syncBlockFindResult.node.attrs.resourceId
|
|
85
|
+
});
|
|
82
86
|
if (!referenceSyncBlockNode) {
|
|
83
87
|
return false;
|
|
84
88
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
} else {
|
|
90
|
+
referenceSyncBlockNode = syncBlockFindResult.node;
|
|
91
|
+
}
|
|
92
|
+
if (!referenceSyncBlockNode) {
|
|
93
|
+
return false;
|
|
94
|
+
}
|
|
95
|
+
var domNode = (0, _copyButton.toDOM)(referenceSyncBlockNode, schema);
|
|
96
|
+
(0, _copyButton.copyDomNode)(domNode, referenceSyncBlockNode.type, selection);
|
|
97
|
+
return true;
|
|
89
98
|
};
|
|
90
99
|
var editSyncedBlockSource = exports.editSyncedBlockSource = function editSyncedBlockSource(syncBlockStore, api) {
|
|
91
100
|
return function (state, dispatch, _view) {
|
|
92
101
|
var _syncBlock$node;
|
|
93
|
-
var syncBlock = (0, _utils2.findSyncBlock)(state);
|
|
102
|
+
var syncBlock = (0, _utils2.findSyncBlock)(state.schema, state.selection);
|
|
94
103
|
var resourceId = syncBlock === null || syncBlock === void 0 || (_syncBlock$node = syncBlock.node) === null || _syncBlock$node === void 0 || (_syncBlock$node = _syncBlock$node.attrs) === null || _syncBlock$node === void 0 ? void 0 : _syncBlock$node.resourceId;
|
|
95
104
|
if (!resourceId) {
|
|
96
105
|
return false;
|
|
@@ -5,28 +5,38 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.isBodiedSyncBlockNode = exports.findSyncBlockOrBodiedSyncBlock = exports.findSyncBlock = exports.findBodiedSyncBlock = exports.canBeConvertedToSyncBlock = void 0;
|
|
7
7
|
var _model = require("@atlaskit/editor-prosemirror/model");
|
|
8
|
+
var _state = require("@atlaskit/editor-prosemirror/state");
|
|
8
9
|
var _utils = require("@atlaskit/editor-prosemirror/utils");
|
|
9
|
-
var _editorSyncedBlockProvider = require("@atlaskit/editor-synced-block-provider");
|
|
10
10
|
var _editorTables = require("@atlaskit/editor-tables");
|
|
11
|
-
var findSyncBlock = exports.findSyncBlock = function findSyncBlock(
|
|
12
|
-
var syncBlock =
|
|
13
|
-
return (0, _utils.findSelectedNodeOfType)(syncBlock)(selection
|
|
11
|
+
var findSyncBlock = exports.findSyncBlock = function findSyncBlock(schema, selection) {
|
|
12
|
+
var syncBlock = schema.nodes.syncBlock;
|
|
13
|
+
return (0, _utils.findSelectedNodeOfType)(syncBlock)(selection);
|
|
14
14
|
};
|
|
15
|
-
var findBodiedSyncBlock = exports.findBodiedSyncBlock = function findBodiedSyncBlock(
|
|
16
|
-
|
|
17
|
-
return (0, _utils.findSelectedNodeOfType)(bodiedSyncBlock)(selection || state.selection) || (0, _utils.findParentNodeOfType)(bodiedSyncBlock)(selection || state.selection);
|
|
15
|
+
var findBodiedSyncBlock = exports.findBodiedSyncBlock = function findBodiedSyncBlock(schema, selection) {
|
|
16
|
+
return (0, _utils.findSelectedNodeOfType)(schema.nodes.bodiedSyncBlock)(selection) || (0, _utils.findParentNodeOfType)(schema.nodes.bodiedSyncBlock)(selection);
|
|
18
17
|
};
|
|
19
|
-
var findSyncBlockOrBodiedSyncBlock = exports.findSyncBlockOrBodiedSyncBlock = function findSyncBlockOrBodiedSyncBlock(
|
|
20
|
-
return findSyncBlock(
|
|
18
|
+
var findSyncBlockOrBodiedSyncBlock = exports.findSyncBlockOrBodiedSyncBlock = function findSyncBlockOrBodiedSyncBlock(schema, selection) {
|
|
19
|
+
return findSyncBlock(schema, selection) || findBodiedSyncBlock(schema, selection);
|
|
21
20
|
};
|
|
22
21
|
var isBodiedSyncBlockNode = exports.isBodiedSyncBlockNode = function isBodiedSyncBlockNode(node, bodiedSyncBlock) {
|
|
23
22
|
return node.type === bodiedSyncBlock;
|
|
24
23
|
};
|
|
24
|
+
var UNSUPPORTED_NODE_TYPES = new Set(['inlineExtension', 'extension', 'bodiedExtension', 'syncBlock', 'bodiedSyncBlock']);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Checks whether the selection can be converted to sync block
|
|
28
|
+
*
|
|
29
|
+
* @param selection - the current editor selection to validate for sync block conversion
|
|
30
|
+
* @returns A fragment containing the content to include in the synced block,
|
|
31
|
+
* stripping out unsupported marks (breakout on codeblock/expand/layout), as well as from and to positions,
|
|
32
|
+
* or false if conversion is not possible
|
|
33
|
+
*/
|
|
25
34
|
var canBeConvertedToSyncBlock = exports.canBeConvertedToSyncBlock = function canBeConvertedToSyncBlock(selection) {
|
|
35
|
+
var schema = selection.$from.doc.type.schema;
|
|
36
|
+
var nodes = schema.nodes;
|
|
26
37
|
var from = selection.from;
|
|
27
38
|
var to = selection.to;
|
|
28
|
-
var
|
|
29
|
-
var contentToInclude;
|
|
39
|
+
var contentToInclude = selection.content().content;
|
|
30
40
|
if (selection instanceof _editorTables.CellSelection) {
|
|
31
41
|
var table = (0, _editorTables.findTable)(selection);
|
|
32
42
|
if (!table) {
|
|
@@ -35,35 +45,41 @@ var canBeConvertedToSyncBlock = exports.canBeConvertedToSyncBlock = function can
|
|
|
35
45
|
contentToInclude = _model.Fragment.from([table.node]);
|
|
36
46
|
from = table.pos;
|
|
37
47
|
to = table.pos + table.node.nodeSize;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return false;
|
|
48
|
+
} else if (selection instanceof _state.TextSelection) {
|
|
49
|
+
var trueParent = (0, _utils.findParentNodeOfType)([nodes.bulletList, nodes.orderedList, nodes.taskList, nodes.blockquote])(selection);
|
|
50
|
+
if (trueParent) {
|
|
51
|
+
contentToInclude = _model.Fragment.from([trueParent.node]);
|
|
52
|
+
from = trueParent.pos;
|
|
53
|
+
to = trueParent.pos + trueParent.node.nodeSize;
|
|
54
|
+
}
|
|
46
55
|
}
|
|
47
|
-
var syncBlockSchema = (0, _editorSyncedBlockProvider.getDefaultSyncBlockSchema)();
|
|
48
56
|
var canBeConverted = true;
|
|
49
57
|
selection.$from.doc.nodesBetween(from, to, function (node) {
|
|
50
|
-
if (
|
|
58
|
+
if (UNSUPPORTED_NODE_TYPES.has(node.type.name)) {
|
|
51
59
|
canBeConverted = false;
|
|
52
60
|
return false;
|
|
53
61
|
}
|
|
54
|
-
node.marks.forEach(function (mark) {
|
|
55
|
-
if (!(mark.type.name in syncBlockSchema.marks)) {
|
|
56
|
-
canBeConverted = false;
|
|
57
|
-
return false;
|
|
58
|
-
}
|
|
59
|
-
});
|
|
60
62
|
});
|
|
61
63
|
if (!canBeConverted) {
|
|
62
64
|
return false;
|
|
63
65
|
}
|
|
66
|
+
contentToInclude = removeBreakoutMarks(contentToInclude);
|
|
64
67
|
return {
|
|
65
68
|
contentToInclude: contentToInclude,
|
|
66
69
|
from: from,
|
|
67
70
|
to: to
|
|
68
71
|
};
|
|
72
|
+
};
|
|
73
|
+
var removeBreakoutMarks = function removeBreakoutMarks(content) {
|
|
74
|
+
var nodes = [];
|
|
75
|
+
|
|
76
|
+
// we only need to recurse at the top level, because breakout has to be on a top level
|
|
77
|
+
content.forEach(function (node) {
|
|
78
|
+
var filteredMarks = node.marks.filter(function (mark) {
|
|
79
|
+
return mark.type.name !== 'breakout';
|
|
80
|
+
});
|
|
81
|
+
var newNode = node.type.create(node.attrs, node.content, filteredMarks);
|
|
82
|
+
nodes.push(newNode);
|
|
83
|
+
});
|
|
84
|
+
return _model.Fragment.from(nodes);
|
|
69
85
|
};
|
|
@@ -45,6 +45,9 @@ var syncedBlockPlugin = exports.syncedBlockPlugin = function syncedBlockPlugin(_
|
|
|
45
45
|
}];
|
|
46
46
|
},
|
|
47
47
|
commands: {
|
|
48
|
+
copySyncedBlockReferenceToClipboard: function copySyncedBlockReferenceToClipboard() {
|
|
49
|
+
return _editorCommands.copySyncedBlockReferenceToClipboardEditorCommand;
|
|
50
|
+
},
|
|
48
51
|
insertSyncedBlock: function insertSyncedBlock() {
|
|
49
52
|
return function (_ref2) {
|
|
50
53
|
var tr = _ref2.tr;
|
|
@@ -1,25 +1,38 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
|
|
4
|
+
var _typeof = require("@babel/runtime/helpers/typeof");
|
|
4
5
|
Object.defineProperty(exports, "__esModule", {
|
|
5
6
|
value: true
|
|
6
7
|
});
|
|
7
|
-
exports.
|
|
8
|
-
var _react =
|
|
8
|
+
exports.CreateOrCopySyncedBlockDropdownItem = void 0;
|
|
9
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
9
10
|
var _reactIntlNext = require("react-intl-next");
|
|
11
|
+
var _hooks = require("@atlaskit/editor-common/hooks");
|
|
10
12
|
var _messages = require("@atlaskit/editor-common/messages");
|
|
11
13
|
var _editorToolbar = require("@atlaskit/editor-toolbar");
|
|
12
14
|
var _lozenge = _interopRequireDefault(require("@atlaskit/lozenge"));
|
|
13
15
|
var _compiled = require("@atlaskit/primitives/compiled");
|
|
14
16
|
var _utils = require("../pm-plugins/utils/utils");
|
|
15
|
-
var
|
|
16
|
-
|
|
17
|
+
function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
|
|
18
|
+
var CreateSyncedBlockDropdownItem = function CreateSyncedBlockDropdownItem(_ref) {
|
|
17
19
|
var api = _ref.api;
|
|
18
20
|
var _useIntl = (0, _reactIntlNext.useIntl)(),
|
|
19
21
|
formatMessage = _useIntl.formatMessage;
|
|
20
|
-
var
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
var _useSharedPluginState = (0, _hooks.useSharedPluginStateWithSelector)(api, ['selection', 'blockControls'], function (states) {
|
|
23
|
+
var _states$selectionStat, _states$blockControls;
|
|
24
|
+
return {
|
|
25
|
+
selection: (_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection,
|
|
26
|
+
activeNode: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.activeNode
|
|
27
|
+
};
|
|
28
|
+
}),
|
|
29
|
+
selection = _useSharedPluginState.selection,
|
|
30
|
+
activeNode = _useSharedPluginState.activeNode;
|
|
31
|
+
var isNested = activeNode && activeNode.rootPos !== activeNode.pos;
|
|
32
|
+
var canBeConverted = (0, _react.useMemo)(function () {
|
|
33
|
+
return selection && (0, _utils.canBeConvertedToSyncBlock)(selection);
|
|
34
|
+
}, [selection]);
|
|
35
|
+
if (isNested || !canBeConverted) {
|
|
23
36
|
return null;
|
|
24
37
|
}
|
|
25
38
|
var onClick = function onClick() {
|
|
@@ -37,7 +50,49 @@ var CreateSyncedBlockDropdownItem = exports.CreateSyncedBlockDropdownItem = func
|
|
|
37
50
|
}, /*#__PURE__*/_react.default.createElement(_compiled.Flex, {
|
|
38
51
|
alignItems: "center",
|
|
39
52
|
gap: "space.050"
|
|
40
|
-
}, /*#__PURE__*/_react.default.createElement(_compiled.Text, null,
|
|
53
|
+
}, /*#__PURE__*/_react.default.createElement(_compiled.Text, null, formatMessage(_messages.blockMenuMessages.createSyncedBlock)), /*#__PURE__*/_react.default.createElement(_lozenge.default, {
|
|
41
54
|
appearance: "new"
|
|
42
55
|
}, formatMessage(_messages.blockMenuMessages.newLozenge))));
|
|
56
|
+
};
|
|
57
|
+
var CopySyncedBlockDropdownItem = function CopySyncedBlockDropdownItem(_ref2) {
|
|
58
|
+
var api = _ref2.api;
|
|
59
|
+
var _useIntl2 = (0, _reactIntlNext.useIntl)(),
|
|
60
|
+
formatMessage = _useIntl2.formatMessage;
|
|
61
|
+
var onClick = function onClick() {
|
|
62
|
+
var _api$core3, _api$core4, _api$blockControls2;
|
|
63
|
+
api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(api === null || api === void 0 ? void 0 : api.syncedBlock.commands.copySyncedBlockReferenceToClipboard());
|
|
64
|
+
api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.toggleBlockMenu({
|
|
65
|
+
closeMenu: true
|
|
66
|
+
}));
|
|
67
|
+
};
|
|
68
|
+
return /*#__PURE__*/_react.default.createElement(_editorToolbar.ToolbarDropdownItem, {
|
|
69
|
+
elemBefore: /*#__PURE__*/_react.default.createElement(_editorToolbar.SyncBlocksIcon, {
|
|
70
|
+
label: ""
|
|
71
|
+
}),
|
|
72
|
+
onClick: onClick
|
|
73
|
+
}, /*#__PURE__*/_react.default.createElement(_compiled.Flex, {
|
|
74
|
+
alignItems: "center",
|
|
75
|
+
gap: "space.050"
|
|
76
|
+
}, /*#__PURE__*/_react.default.createElement(_compiled.Text, null, formatMessage(_messages.blockMenuMessages.copySyncedBlock)), /*#__PURE__*/_react.default.createElement(_lozenge.default, {
|
|
77
|
+
appearance: "new"
|
|
78
|
+
}, formatMessage(_messages.blockMenuMessages.newLozenge))));
|
|
79
|
+
};
|
|
80
|
+
var CreateOrCopySyncedBlockDropdownItem = exports.CreateOrCopySyncedBlockDropdownItem = function CreateOrCopySyncedBlockDropdownItem(_ref3) {
|
|
81
|
+
var api = _ref3.api;
|
|
82
|
+
var _useSharedPluginState2 = (0, _hooks.useSharedPluginStateWithSelector)(api, ['blockControls'], function (states) {
|
|
83
|
+
var _states$blockControls2;
|
|
84
|
+
return {
|
|
85
|
+
menuTriggerBy: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.menuTriggerBy
|
|
86
|
+
};
|
|
87
|
+
}),
|
|
88
|
+
menuTriggerBy = _useSharedPluginState2.menuTriggerBy;
|
|
89
|
+
if (menuTriggerBy === 'syncBlock' || menuTriggerBy === 'bodiedSyncBlock') {
|
|
90
|
+
return /*#__PURE__*/_react.default.createElement(CopySyncedBlockDropdownItem, {
|
|
91
|
+
api: api
|
|
92
|
+
});
|
|
93
|
+
} else {
|
|
94
|
+
return /*#__PURE__*/_react.default.createElement(CreateSyncedBlockDropdownItem, {
|
|
95
|
+
api: api
|
|
96
|
+
});
|
|
97
|
+
}
|
|
43
98
|
};
|
|
@@ -18,7 +18,7 @@ var getBlockMenuComponents = exports.getBlockMenuComponents = function getBlockM
|
|
|
18
18
|
rank: _blockMenu.ADD_BLOCKS_MENU_SECTION_RANK[_blockMenu.CREATE_SYNCED_BLOCK_MENU_ITEM.key]
|
|
19
19
|
},
|
|
20
20
|
component: function component() {
|
|
21
|
-
return /*#__PURE__*/_react.default.createElement(_CreateSyncedBlockDropdownItem.
|
|
21
|
+
return /*#__PURE__*/_react.default.createElement(_CreateSyncedBlockDropdownItem.CreateOrCopySyncedBlockDropdownItem, {
|
|
22
22
|
api: api
|
|
23
23
|
});
|
|
24
24
|
}
|
|
@@ -21,7 +21,7 @@ function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbol
|
|
|
21
21
|
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
22
22
|
var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(state, intl, api, syncBlockStore) {
|
|
23
23
|
var _api$decorations;
|
|
24
|
-
var syncBlockObject = (0, _utils2.findSyncBlockOrBodiedSyncBlock)(state);
|
|
24
|
+
var syncBlockObject = (0, _utils2.findSyncBlockOrBodiedSyncBlock)(state.schema, state.selection);
|
|
25
25
|
if (!syncBlockObject) {
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
@@ -47,7 +47,7 @@ var getToolbarConfig = exports.getToolbarConfig = function getToolbarConfig(stat
|
|
|
47
47
|
title: formatMessage(_messages.syncBlockMessages.copySyncBlockLabel),
|
|
48
48
|
showTitle: false,
|
|
49
49
|
tooltipContent: formatMessage(_messages.syncBlockMessages.copySyncBlockTooltip),
|
|
50
|
-
onClick:
|
|
50
|
+
onClick: _editorCommands.copySyncedBlockReferenceToClipboard
|
|
51
51
|
}, hoverDecorationProps(nodeType, _consts.akEditorSelectedNodeClassName));
|
|
52
52
|
items.push(copyButton);
|
|
53
53
|
var disabled = !syncBlockStore.getSyncBlockURL(syncBlockObject.node.attrs.resourceId);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
2
2
|
import { copyDomNode, toDOM } from '@atlaskit/editor-common/copy-button';
|
|
3
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
3
4
|
import { findSelectedNodeOfType, removeParentNodeOfType, removeSelectedNode } from '@atlaskit/editor-prosemirror/utils';
|
|
4
5
|
import { canBeConvertedToSyncBlock, findSyncBlock, findSyncBlockOrBodiedSyncBlock, isBodiedSyncBlockNode } from '../pm-plugins/utils/utils';
|
|
5
6
|
export const createSyncedBlock = ({
|
|
@@ -48,31 +49,40 @@ export const createSyncedBlock = ({
|
|
|
48
49
|
// Save the new node with empty content to backend
|
|
49
50
|
// This is so that the node can be copied and referenced without the source being saved/published
|
|
50
51
|
syncBlockStore.createBodiedSyncBlockNode(attrs);
|
|
51
|
-
tr.replaceWith(conversionInfo.from - 1, conversionInfo.to, newBodiedSyncBlockNode).scrollIntoView();
|
|
52
|
+
tr.replaceWith(conversionInfo.from > 0 ? conversionInfo.from - 1 : 0, conversionInfo.to, newBodiedSyncBlockNode).scrollIntoView();
|
|
53
|
+
|
|
54
|
+
// set selection to the end of the previous selection + 1 for the position taken up by the start of the new synced block
|
|
55
|
+
tr.setSelection(TextSelection.create(tr.doc, conversionInfo.to + 1));
|
|
52
56
|
}
|
|
53
57
|
|
|
54
58
|
// This transaction will be intercepted in filterTransaction and dispatched when saving to backend succeeds
|
|
55
59
|
// see filterTransaction for more details
|
|
56
60
|
return tr;
|
|
57
61
|
};
|
|
58
|
-
export const
|
|
59
|
-
|
|
60
|
-
|
|
62
|
+
export const copySyncedBlockReferenceToClipboardEditorCommand = ({
|
|
63
|
+
tr
|
|
64
|
+
}) => {
|
|
65
|
+
if (copySyncedBlockReferenceToClipboardInternal(tr.doc.type.schema, tr.selection)) {
|
|
66
|
+
return tr;
|
|
61
67
|
}
|
|
62
|
-
|
|
68
|
+
return null;
|
|
69
|
+
};
|
|
70
|
+
export const copySyncedBlockReferenceToClipboard = (state, _dispatch, _view) => {
|
|
71
|
+
return copySyncedBlockReferenceToClipboardInternal(state.tr.doc.type.schema, state.tr.selection);
|
|
72
|
+
};
|
|
73
|
+
const copySyncedBlockReferenceToClipboardInternal = (schema, selection) => {
|
|
74
|
+
const syncBlockFindResult = findSyncBlockOrBodiedSyncBlock(schema, selection);
|
|
63
75
|
if (!syncBlockFindResult) {
|
|
64
76
|
return false;
|
|
65
77
|
}
|
|
66
|
-
const isBodiedSyncBlock = isBodiedSyncBlockNode(syncBlockFindResult.node,
|
|
78
|
+
const isBodiedSyncBlock = isBodiedSyncBlockNode(syncBlockFindResult.node, schema.nodes.bodiedSyncBlock);
|
|
67
79
|
let referenceSyncBlockNode = null;
|
|
68
80
|
if (isBodiedSyncBlock) {
|
|
69
81
|
const {
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
syncBlock
|
|
73
|
-
}
|
|
82
|
+
nodes: {
|
|
83
|
+
syncBlock
|
|
74
84
|
}
|
|
75
|
-
} =
|
|
85
|
+
} = schema;
|
|
76
86
|
|
|
77
87
|
// create sync block reference node
|
|
78
88
|
referenceSyncBlockNode = syncBlock.createAndFill({
|
|
@@ -87,13 +97,13 @@ export const copySyncedBlockReferenceToClipboard = api => (state, _dispatch, _vi
|
|
|
87
97
|
if (!referenceSyncBlockNode) {
|
|
88
98
|
return false;
|
|
89
99
|
}
|
|
90
|
-
const domNode = toDOM(referenceSyncBlockNode,
|
|
91
|
-
copyDomNode(domNode, referenceSyncBlockNode.type,
|
|
100
|
+
const domNode = toDOM(referenceSyncBlockNode, schema);
|
|
101
|
+
copyDomNode(domNode, referenceSyncBlockNode.type, selection);
|
|
92
102
|
return true;
|
|
93
103
|
};
|
|
94
104
|
export const editSyncedBlockSource = (syncBlockStore, api) => (state, dispatch, _view) => {
|
|
95
105
|
var _syncBlock$node, _syncBlock$node$attrs;
|
|
96
|
-
const syncBlock = findSyncBlock(state);
|
|
106
|
+
const syncBlock = findSyncBlock(state.schema, state.selection);
|
|
97
107
|
const resourceId = syncBlock === null || syncBlock === void 0 ? void 0 : (_syncBlock$node = syncBlock.node) === null || _syncBlock$node === void 0 ? void 0 : (_syncBlock$node$attrs = _syncBlock$node.attrs) === null || _syncBlock$node$attrs === void 0 ? void 0 : _syncBlock$node$attrs.resourceId;
|
|
98
108
|
if (!resourceId) {
|
|
99
109
|
return false;
|
|
@@ -1,28 +1,38 @@
|
|
|
1
1
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
2
3
|
import { findParentNodeOfType, findSelectedNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
3
|
-
import { getDefaultSyncBlockSchema } from '@atlaskit/editor-synced-block-provider';
|
|
4
4
|
import { CellSelection, findTable } from '@atlaskit/editor-tables';
|
|
5
|
-
export const findSyncBlock = (
|
|
5
|
+
export const findSyncBlock = (schema, selection) => {
|
|
6
6
|
const {
|
|
7
7
|
syncBlock
|
|
8
|
-
} =
|
|
9
|
-
return findSelectedNodeOfType(syncBlock)(selection
|
|
8
|
+
} = schema.nodes;
|
|
9
|
+
return findSelectedNodeOfType(syncBlock)(selection);
|
|
10
10
|
};
|
|
11
|
-
export const findBodiedSyncBlock = (
|
|
12
|
-
|
|
13
|
-
bodiedSyncBlock
|
|
14
|
-
} = state.schema.nodes;
|
|
15
|
-
return findSelectedNodeOfType(bodiedSyncBlock)(selection || state.selection) || findParentNodeOfType(bodiedSyncBlock)(selection || state.selection);
|
|
11
|
+
export const findBodiedSyncBlock = (schema, selection) => {
|
|
12
|
+
return findSelectedNodeOfType(schema.nodes.bodiedSyncBlock)(selection) || findParentNodeOfType(schema.nodes.bodiedSyncBlock)(selection);
|
|
16
13
|
};
|
|
17
|
-
export const findSyncBlockOrBodiedSyncBlock = (
|
|
18
|
-
return findSyncBlock(
|
|
14
|
+
export const findSyncBlockOrBodiedSyncBlock = (schema, selection) => {
|
|
15
|
+
return findSyncBlock(schema, selection) || findBodiedSyncBlock(schema, selection);
|
|
19
16
|
};
|
|
20
17
|
export const isBodiedSyncBlockNode = (node, bodiedSyncBlock) => node.type === bodiedSyncBlock;
|
|
18
|
+
const UNSUPPORTED_NODE_TYPES = new Set(['inlineExtension', 'extension', 'bodiedExtension', 'syncBlock', 'bodiedSyncBlock']);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Checks whether the selection can be converted to sync block
|
|
22
|
+
*
|
|
23
|
+
* @param selection - the current editor selection to validate for sync block conversion
|
|
24
|
+
* @returns A fragment containing the content to include in the synced block,
|
|
25
|
+
* stripping out unsupported marks (breakout on codeblock/expand/layout), as well as from and to positions,
|
|
26
|
+
* or false if conversion is not possible
|
|
27
|
+
*/
|
|
21
28
|
export const canBeConvertedToSyncBlock = selection => {
|
|
29
|
+
const schema = selection.$from.doc.type.schema;
|
|
30
|
+
const {
|
|
31
|
+
nodes
|
|
32
|
+
} = schema;
|
|
22
33
|
let from = selection.from;
|
|
23
34
|
let to = selection.to;
|
|
24
|
-
let
|
|
25
|
-
let contentToInclude;
|
|
35
|
+
let contentToInclude = selection.content().content;
|
|
26
36
|
if (selection instanceof CellSelection) {
|
|
27
37
|
const table = findTable(selection);
|
|
28
38
|
if (!table) {
|
|
@@ -31,35 +41,39 @@ export const canBeConvertedToSyncBlock = selection => {
|
|
|
31
41
|
contentToInclude = Fragment.from([table.node]);
|
|
32
42
|
from = table.pos;
|
|
33
43
|
to = table.pos + table.node.nodeSize;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
return false;
|
|
44
|
+
} else if (selection instanceof TextSelection) {
|
|
45
|
+
const trueParent = findParentNodeOfType([nodes.bulletList, nodes.orderedList, nodes.taskList, nodes.blockquote])(selection);
|
|
46
|
+
if (trueParent) {
|
|
47
|
+
contentToInclude = Fragment.from([trueParent.node]);
|
|
48
|
+
from = trueParent.pos;
|
|
49
|
+
to = trueParent.pos + trueParent.node.nodeSize;
|
|
50
|
+
}
|
|
42
51
|
}
|
|
43
|
-
const syncBlockSchema = getDefaultSyncBlockSchema();
|
|
44
52
|
let canBeConverted = true;
|
|
45
53
|
selection.$from.doc.nodesBetween(from, to, node => {
|
|
46
|
-
if (
|
|
54
|
+
if (UNSUPPORTED_NODE_TYPES.has(node.type.name)) {
|
|
47
55
|
canBeConverted = false;
|
|
48
56
|
return false;
|
|
49
57
|
}
|
|
50
|
-
node.marks.forEach(mark => {
|
|
51
|
-
if (!(mark.type.name in syncBlockSchema.marks)) {
|
|
52
|
-
canBeConverted = false;
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
});
|
|
56
58
|
});
|
|
57
59
|
if (!canBeConverted) {
|
|
58
60
|
return false;
|
|
59
61
|
}
|
|
62
|
+
contentToInclude = removeBreakoutMarks(contentToInclude);
|
|
60
63
|
return {
|
|
61
64
|
contentToInclude,
|
|
62
65
|
from,
|
|
63
66
|
to
|
|
64
67
|
};
|
|
68
|
+
};
|
|
69
|
+
const removeBreakoutMarks = content => {
|
|
70
|
+
const nodes = [];
|
|
71
|
+
|
|
72
|
+
// we only need to recurse at the top level, because breakout has to be on a top level
|
|
73
|
+
content.forEach(node => {
|
|
74
|
+
const filteredMarks = node.marks.filter(mark => mark.type.name !== 'breakout');
|
|
75
|
+
const newNode = node.type.create(node.attrs, node.content, filteredMarks);
|
|
76
|
+
nodes.push(newNode);
|
|
77
|
+
});
|
|
78
|
+
return Fragment.from(nodes);
|
|
65
79
|
};
|
|
@@ -4,7 +4,7 @@ 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';
|
|
6
6
|
import { flushBodiedSyncBlocks } from './editor-actions';
|
|
7
|
-
import { createSyncedBlock } from './editor-commands';
|
|
7
|
+
import { copySyncedBlockReferenceToClipboardEditorCommand, createSyncedBlock } from './editor-commands';
|
|
8
8
|
import { createPlugin } from './pm-plugins/main';
|
|
9
9
|
import { getBlockMenuComponents } from './ui/block-menu-components';
|
|
10
10
|
import { DeleteConfirmationModal } from './ui/DeleteConfirmationModal';
|
|
@@ -37,6 +37,7 @@ export const syncedBlockPlugin = ({
|
|
|
37
37
|
}];
|
|
38
38
|
},
|
|
39
39
|
commands: {
|
|
40
|
+
copySyncedBlockReferenceToClipboard: () => copySyncedBlockReferenceToClipboardEditorCommand,
|
|
40
41
|
insertSyncedBlock: () => ({
|
|
41
42
|
tr
|
|
42
43
|
}) => createSyncedBlock({
|
|
@@ -1,20 +1,30 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
2
|
import { useIntl } from 'react-intl-next';
|
|
3
|
+
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
3
4
|
import { blockMenuMessages } from '@atlaskit/editor-common/messages';
|
|
4
5
|
import { SyncBlocksIcon, ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
|
|
5
6
|
import Lozenge from '@atlaskit/lozenge';
|
|
6
7
|
import { Flex, Text } from '@atlaskit/primitives/compiled';
|
|
7
8
|
import { canBeConvertedToSyncBlock } from '../pm-plugins/utils/utils';
|
|
8
|
-
|
|
9
|
+
const CreateSyncedBlockDropdownItem = ({
|
|
9
10
|
api
|
|
10
11
|
}) => {
|
|
11
|
-
var _api$selection, _api$selection$shared, _api$selection$shared2;
|
|
12
12
|
const {
|
|
13
13
|
formatMessage
|
|
14
14
|
} = useIntl();
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
const {
|
|
16
|
+
selection,
|
|
17
|
+
activeNode
|
|
18
|
+
} = useSharedPluginStateWithSelector(api, ['selection', 'blockControls'], states => {
|
|
19
|
+
var _states$selectionStat, _states$blockControls;
|
|
20
|
+
return {
|
|
21
|
+
selection: (_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection,
|
|
22
|
+
activeNode: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.activeNode
|
|
23
|
+
};
|
|
24
|
+
});
|
|
25
|
+
const isNested = activeNode && activeNode.rootPos !== activeNode.pos;
|
|
26
|
+
const canBeConverted = useMemo(() => selection && canBeConvertedToSyncBlock(selection), [selection]);
|
|
27
|
+
if (isNested || !canBeConverted) {
|
|
18
28
|
return null;
|
|
19
29
|
}
|
|
20
30
|
const onClick = () => {
|
|
@@ -32,7 +42,53 @@ export const CreateSyncedBlockDropdownItem = ({
|
|
|
32
42
|
}, /*#__PURE__*/React.createElement(Flex, {
|
|
33
43
|
alignItems: "center",
|
|
34
44
|
gap: "space.050"
|
|
35
|
-
}, /*#__PURE__*/React.createElement(Text, null,
|
|
45
|
+
}, /*#__PURE__*/React.createElement(Text, null, formatMessage(blockMenuMessages.createSyncedBlock)), /*#__PURE__*/React.createElement(Lozenge, {
|
|
46
|
+
appearance: "new"
|
|
47
|
+
}, formatMessage(blockMenuMessages.newLozenge))));
|
|
48
|
+
};
|
|
49
|
+
const CopySyncedBlockDropdownItem = ({
|
|
50
|
+
api
|
|
51
|
+
}) => {
|
|
52
|
+
const {
|
|
53
|
+
formatMessage
|
|
54
|
+
} = useIntl();
|
|
55
|
+
const onClick = () => {
|
|
56
|
+
var _api$core3, _api$core4, _api$blockControls2, _api$blockControls2$c;
|
|
57
|
+
api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(api === null || api === void 0 ? void 0 : api.syncedBlock.commands.copySyncedBlockReferenceToClipboard());
|
|
58
|
+
api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : (_api$blockControls2$c = _api$blockControls2.commands) === null || _api$blockControls2$c === void 0 ? void 0 : _api$blockControls2$c.toggleBlockMenu({
|
|
59
|
+
closeMenu: true
|
|
60
|
+
}));
|
|
61
|
+
};
|
|
62
|
+
return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
|
|
63
|
+
elemBefore: /*#__PURE__*/React.createElement(SyncBlocksIcon, {
|
|
64
|
+
label: ""
|
|
65
|
+
}),
|
|
66
|
+
onClick: onClick
|
|
67
|
+
}, /*#__PURE__*/React.createElement(Flex, {
|
|
68
|
+
alignItems: "center",
|
|
69
|
+
gap: "space.050"
|
|
70
|
+
}, /*#__PURE__*/React.createElement(Text, null, formatMessage(blockMenuMessages.copySyncedBlock)), /*#__PURE__*/React.createElement(Lozenge, {
|
|
36
71
|
appearance: "new"
|
|
37
72
|
}, formatMessage(blockMenuMessages.newLozenge))));
|
|
73
|
+
};
|
|
74
|
+
export const CreateOrCopySyncedBlockDropdownItem = ({
|
|
75
|
+
api
|
|
76
|
+
}) => {
|
|
77
|
+
const {
|
|
78
|
+
menuTriggerBy
|
|
79
|
+
} = useSharedPluginStateWithSelector(api, ['blockControls'], states => {
|
|
80
|
+
var _states$blockControls2;
|
|
81
|
+
return {
|
|
82
|
+
menuTriggerBy: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.menuTriggerBy
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
if (menuTriggerBy === 'syncBlock' || menuTriggerBy === 'bodiedSyncBlock') {
|
|
86
|
+
return /*#__PURE__*/React.createElement(CopySyncedBlockDropdownItem, {
|
|
87
|
+
api: api
|
|
88
|
+
});
|
|
89
|
+
} else {
|
|
90
|
+
return /*#__PURE__*/React.createElement(CreateSyncedBlockDropdownItem, {
|
|
91
|
+
api: api
|
|
92
|
+
});
|
|
93
|
+
}
|
|
38
94
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ADD_BLOCKS_MENU_SECTION, ADD_BLOCKS_MENU_SECTION_RANK, CREATE_SYNCED_BLOCK_MENU_ITEM } from '@atlaskit/editor-common/block-menu';
|
|
3
|
-
import {
|
|
3
|
+
import { CreateOrCopySyncedBlockDropdownItem } from './CreateSyncedBlockDropdownItem';
|
|
4
4
|
export const getBlockMenuComponents = api => {
|
|
5
5
|
return [{
|
|
6
6
|
type: 'block-menu-item',
|
|
@@ -10,7 +10,7 @@ export const getBlockMenuComponents = api => {
|
|
|
10
10
|
key: ADD_BLOCKS_MENU_SECTION.key,
|
|
11
11
|
rank: ADD_BLOCKS_MENU_SECTION_RANK[CREATE_SYNCED_BLOCK_MENU_ITEM.key]
|
|
12
12
|
},
|
|
13
|
-
component: () => /*#__PURE__*/React.createElement(
|
|
13
|
+
component: () => /*#__PURE__*/React.createElement(CreateOrCopySyncedBlockDropdownItem, {
|
|
14
14
|
api: api
|
|
15
15
|
})
|
|
16
16
|
}];
|
|
@@ -9,7 +9,7 @@ import { copySyncedBlockReferenceToClipboard, editSyncedBlockSource, removeSynce
|
|
|
9
9
|
import { findSyncBlockOrBodiedSyncBlock, isBodiedSyncBlockNode } from '../pm-plugins/utils/utils';
|
|
10
10
|
export const getToolbarConfig = (state, intl, api, syncBlockStore) => {
|
|
11
11
|
var _api$decorations;
|
|
12
|
-
const syncBlockObject = findSyncBlockOrBodiedSyncBlock(state);
|
|
12
|
+
const syncBlockObject = findSyncBlockOrBodiedSyncBlock(state.schema, state.selection);
|
|
13
13
|
if (!syncBlockObject) {
|
|
14
14
|
return;
|
|
15
15
|
}
|
|
@@ -41,7 +41,7 @@ export const getToolbarConfig = (state, intl, api, syncBlockStore) => {
|
|
|
41
41
|
title: formatMessage(messages.copySyncBlockLabel),
|
|
42
42
|
showTitle: false,
|
|
43
43
|
tooltipContent: formatMessage(messages.copySyncBlockTooltip),
|
|
44
|
-
onClick: copySyncedBlockReferenceToClipboard
|
|
44
|
+
onClick: copySyncedBlockReferenceToClipboard,
|
|
45
45
|
...hoverDecorationProps(nodeType, akEditorSelectedNodeClassName)
|
|
46
46
|
};
|
|
47
47
|
items.push(copyButton);
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
|
|
2
2
|
import { copyDomNode, toDOM } from '@atlaskit/editor-common/copy-button';
|
|
3
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
3
4
|
import { findSelectedNodeOfType, removeParentNodeOfType, removeSelectedNode } from '@atlaskit/editor-prosemirror/utils';
|
|
4
5
|
import { canBeConvertedToSyncBlock, findSyncBlock, findSyncBlockOrBodiedSyncBlock, isBodiedSyncBlockNode } from '../pm-plugins/utils/utils';
|
|
5
6
|
export var createSyncedBlock = function createSyncedBlock(_ref) {
|
|
@@ -42,49 +43,57 @@ export var createSyncedBlock = function createSyncedBlock(_ref) {
|
|
|
42
43
|
// Save the new node with empty content to backend
|
|
43
44
|
// This is so that the node can be copied and referenced without the source being saved/published
|
|
44
45
|
syncBlockStore.createBodiedSyncBlockNode(_attrs);
|
|
45
|
-
tr.replaceWith(conversionInfo.from - 1, conversionInfo.to, _newBodiedSyncBlockNode).scrollIntoView();
|
|
46
|
+
tr.replaceWith(conversionInfo.from > 0 ? conversionInfo.from - 1 : 0, conversionInfo.to, _newBodiedSyncBlockNode).scrollIntoView();
|
|
47
|
+
|
|
48
|
+
// set selection to the end of the previous selection + 1 for the position taken up by the start of the new synced block
|
|
49
|
+
tr.setSelection(TextSelection.create(tr.doc, conversionInfo.to + 1));
|
|
46
50
|
}
|
|
47
51
|
|
|
48
52
|
// This transaction will be intercepted in filterTransaction and dispatched when saving to backend succeeds
|
|
49
53
|
// see filterTransaction for more details
|
|
50
54
|
return tr;
|
|
51
55
|
};
|
|
52
|
-
export var
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
56
|
+
export var copySyncedBlockReferenceToClipboardEditorCommand = function copySyncedBlockReferenceToClipboardEditorCommand(_ref2) {
|
|
57
|
+
var tr = _ref2.tr;
|
|
58
|
+
if (copySyncedBlockReferenceToClipboardInternal(tr.doc.type.schema, tr.selection)) {
|
|
59
|
+
return tr;
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
};
|
|
63
|
+
export var copySyncedBlockReferenceToClipboard = function copySyncedBlockReferenceToClipboard(state, _dispatch, _view) {
|
|
64
|
+
return copySyncedBlockReferenceToClipboardInternal(state.tr.doc.type.schema, state.tr.selection);
|
|
65
|
+
};
|
|
66
|
+
var copySyncedBlockReferenceToClipboardInternal = function copySyncedBlockReferenceToClipboardInternal(schema, selection) {
|
|
67
|
+
var syncBlockFindResult = findSyncBlockOrBodiedSyncBlock(schema, selection);
|
|
68
|
+
if (!syncBlockFindResult) {
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
var isBodiedSyncBlock = isBodiedSyncBlockNode(syncBlockFindResult.node, schema.nodes.bodiedSyncBlock);
|
|
72
|
+
var referenceSyncBlockNode = null;
|
|
73
|
+
if (isBodiedSyncBlock) {
|
|
74
|
+
var syncBlock = schema.nodes.syncBlock;
|
|
65
75
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
if (!referenceSyncBlockNode) {
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
} else {
|
|
74
|
-
referenceSyncBlockNode = syncBlockFindResult.node;
|
|
75
|
-
}
|
|
76
|
+
// create sync block reference node
|
|
77
|
+
referenceSyncBlockNode = syncBlock.createAndFill({
|
|
78
|
+
resourceId: syncBlockFindResult.node.attrs.resourceId
|
|
79
|
+
});
|
|
76
80
|
if (!referenceSyncBlockNode) {
|
|
77
81
|
return false;
|
|
78
82
|
}
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
+
} else {
|
|
84
|
+
referenceSyncBlockNode = syncBlockFindResult.node;
|
|
85
|
+
}
|
|
86
|
+
if (!referenceSyncBlockNode) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
var domNode = toDOM(referenceSyncBlockNode, schema);
|
|
90
|
+
copyDomNode(domNode, referenceSyncBlockNode.type, selection);
|
|
91
|
+
return true;
|
|
83
92
|
};
|
|
84
93
|
export var editSyncedBlockSource = function editSyncedBlockSource(syncBlockStore, api) {
|
|
85
94
|
return function (state, dispatch, _view) {
|
|
86
95
|
var _syncBlock$node;
|
|
87
|
-
var syncBlock = findSyncBlock(state);
|
|
96
|
+
var syncBlock = findSyncBlock(state.schema, state.selection);
|
|
88
97
|
var resourceId = syncBlock === null || syncBlock === void 0 || (_syncBlock$node = syncBlock.node) === null || _syncBlock$node === void 0 || (_syncBlock$node = _syncBlock$node.attrs) === null || _syncBlock$node === void 0 ? void 0 : _syncBlock$node.resourceId;
|
|
89
98
|
if (!resourceId) {
|
|
90
99
|
return false;
|
|
@@ -1,26 +1,36 @@
|
|
|
1
1
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
+
import { TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
2
3
|
import { findParentNodeOfType, findSelectedNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
3
|
-
import { getDefaultSyncBlockSchema } from '@atlaskit/editor-synced-block-provider';
|
|
4
4
|
import { CellSelection, findTable } from '@atlaskit/editor-tables';
|
|
5
|
-
export var findSyncBlock = function findSyncBlock(
|
|
6
|
-
var syncBlock =
|
|
7
|
-
return findSelectedNodeOfType(syncBlock)(selection
|
|
5
|
+
export var findSyncBlock = function findSyncBlock(schema, selection) {
|
|
6
|
+
var syncBlock = schema.nodes.syncBlock;
|
|
7
|
+
return findSelectedNodeOfType(syncBlock)(selection);
|
|
8
8
|
};
|
|
9
|
-
export var findBodiedSyncBlock = function findBodiedSyncBlock(
|
|
10
|
-
|
|
11
|
-
return findSelectedNodeOfType(bodiedSyncBlock)(selection || state.selection) || findParentNodeOfType(bodiedSyncBlock)(selection || state.selection);
|
|
9
|
+
export var findBodiedSyncBlock = function findBodiedSyncBlock(schema, selection) {
|
|
10
|
+
return findSelectedNodeOfType(schema.nodes.bodiedSyncBlock)(selection) || findParentNodeOfType(schema.nodes.bodiedSyncBlock)(selection);
|
|
12
11
|
};
|
|
13
|
-
export var findSyncBlockOrBodiedSyncBlock = function findSyncBlockOrBodiedSyncBlock(
|
|
14
|
-
return findSyncBlock(
|
|
12
|
+
export var findSyncBlockOrBodiedSyncBlock = function findSyncBlockOrBodiedSyncBlock(schema, selection) {
|
|
13
|
+
return findSyncBlock(schema, selection) || findBodiedSyncBlock(schema, selection);
|
|
15
14
|
};
|
|
16
15
|
export var isBodiedSyncBlockNode = function isBodiedSyncBlockNode(node, bodiedSyncBlock) {
|
|
17
16
|
return node.type === bodiedSyncBlock;
|
|
18
17
|
};
|
|
18
|
+
var UNSUPPORTED_NODE_TYPES = new Set(['inlineExtension', 'extension', 'bodiedExtension', 'syncBlock', 'bodiedSyncBlock']);
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Checks whether the selection can be converted to sync block
|
|
22
|
+
*
|
|
23
|
+
* @param selection - the current editor selection to validate for sync block conversion
|
|
24
|
+
* @returns A fragment containing the content to include in the synced block,
|
|
25
|
+
* stripping out unsupported marks (breakout on codeblock/expand/layout), as well as from and to positions,
|
|
26
|
+
* or false if conversion is not possible
|
|
27
|
+
*/
|
|
19
28
|
export var canBeConvertedToSyncBlock = function canBeConvertedToSyncBlock(selection) {
|
|
29
|
+
var schema = selection.$from.doc.type.schema;
|
|
30
|
+
var nodes = schema.nodes;
|
|
20
31
|
var from = selection.from;
|
|
21
32
|
var to = selection.to;
|
|
22
|
-
var
|
|
23
|
-
var contentToInclude;
|
|
33
|
+
var contentToInclude = selection.content().content;
|
|
24
34
|
if (selection instanceof CellSelection) {
|
|
25
35
|
var table = findTable(selection);
|
|
26
36
|
if (!table) {
|
|
@@ -29,35 +39,41 @@ export var canBeConvertedToSyncBlock = function canBeConvertedToSyncBlock(select
|
|
|
29
39
|
contentToInclude = Fragment.from([table.node]);
|
|
30
40
|
from = table.pos;
|
|
31
41
|
to = table.pos + table.node.nodeSize;
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return false;
|
|
42
|
+
} else if (selection instanceof TextSelection) {
|
|
43
|
+
var trueParent = findParentNodeOfType([nodes.bulletList, nodes.orderedList, nodes.taskList, nodes.blockquote])(selection);
|
|
44
|
+
if (trueParent) {
|
|
45
|
+
contentToInclude = Fragment.from([trueParent.node]);
|
|
46
|
+
from = trueParent.pos;
|
|
47
|
+
to = trueParent.pos + trueParent.node.nodeSize;
|
|
48
|
+
}
|
|
40
49
|
}
|
|
41
|
-
var syncBlockSchema = getDefaultSyncBlockSchema();
|
|
42
50
|
var canBeConverted = true;
|
|
43
51
|
selection.$from.doc.nodesBetween(from, to, function (node) {
|
|
44
|
-
if (
|
|
52
|
+
if (UNSUPPORTED_NODE_TYPES.has(node.type.name)) {
|
|
45
53
|
canBeConverted = false;
|
|
46
54
|
return false;
|
|
47
55
|
}
|
|
48
|
-
node.marks.forEach(function (mark) {
|
|
49
|
-
if (!(mark.type.name in syncBlockSchema.marks)) {
|
|
50
|
-
canBeConverted = false;
|
|
51
|
-
return false;
|
|
52
|
-
}
|
|
53
|
-
});
|
|
54
56
|
});
|
|
55
57
|
if (!canBeConverted) {
|
|
56
58
|
return false;
|
|
57
59
|
}
|
|
60
|
+
contentToInclude = removeBreakoutMarks(contentToInclude);
|
|
58
61
|
return {
|
|
59
62
|
contentToInclude: contentToInclude,
|
|
60
63
|
from: from,
|
|
61
64
|
to: to
|
|
62
65
|
};
|
|
66
|
+
};
|
|
67
|
+
var removeBreakoutMarks = function removeBreakoutMarks(content) {
|
|
68
|
+
var nodes = [];
|
|
69
|
+
|
|
70
|
+
// we only need to recurse at the top level, because breakout has to be on a top level
|
|
71
|
+
content.forEach(function (node) {
|
|
72
|
+
var filteredMarks = node.marks.filter(function (mark) {
|
|
73
|
+
return mark.type.name !== 'breakout';
|
|
74
|
+
});
|
|
75
|
+
var newNode = node.type.create(node.attrs, node.content, filteredMarks);
|
|
76
|
+
nodes.push(newNode);
|
|
77
|
+
});
|
|
78
|
+
return Fragment.from(nodes);
|
|
63
79
|
};
|
|
@@ -4,7 +4,7 @@ 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';
|
|
6
6
|
import { flushBodiedSyncBlocks as _flushBodiedSyncBlocks } from './editor-actions';
|
|
7
|
-
import { createSyncedBlock } from './editor-commands';
|
|
7
|
+
import { copySyncedBlockReferenceToClipboardEditorCommand, createSyncedBlock } from './editor-commands';
|
|
8
8
|
import { createPlugin } from './pm-plugins/main';
|
|
9
9
|
import { getBlockMenuComponents } from './ui/block-menu-components';
|
|
10
10
|
import { DeleteConfirmationModal } from './ui/DeleteConfirmationModal';
|
|
@@ -38,6 +38,9 @@ export var syncedBlockPlugin = function syncedBlockPlugin(_ref) {
|
|
|
38
38
|
}];
|
|
39
39
|
},
|
|
40
40
|
commands: {
|
|
41
|
+
copySyncedBlockReferenceToClipboard: function copySyncedBlockReferenceToClipboard() {
|
|
42
|
+
return copySyncedBlockReferenceToClipboardEditorCommand;
|
|
43
|
+
},
|
|
41
44
|
insertSyncedBlock: function insertSyncedBlock() {
|
|
42
45
|
return function (_ref2) {
|
|
43
46
|
var tr = _ref2.tr;
|
|
@@ -1,18 +1,29 @@
|
|
|
1
|
-
import React from 'react';
|
|
1
|
+
import React, { useMemo } from 'react';
|
|
2
2
|
import { useIntl } from 'react-intl-next';
|
|
3
|
+
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
3
4
|
import { blockMenuMessages } from '@atlaskit/editor-common/messages';
|
|
4
5
|
import { SyncBlocksIcon, ToolbarDropdownItem } from '@atlaskit/editor-toolbar';
|
|
5
6
|
import Lozenge from '@atlaskit/lozenge';
|
|
6
7
|
import { Flex, Text } from '@atlaskit/primitives/compiled';
|
|
7
8
|
import { canBeConvertedToSyncBlock } from '../pm-plugins/utils/utils';
|
|
8
|
-
|
|
9
|
-
var _api$selection;
|
|
9
|
+
var CreateSyncedBlockDropdownItem = function CreateSyncedBlockDropdownItem(_ref) {
|
|
10
10
|
var api = _ref.api;
|
|
11
11
|
var _useIntl = useIntl(),
|
|
12
12
|
formatMessage = _useIntl.formatMessage;
|
|
13
|
-
var
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
var _useSharedPluginState = useSharedPluginStateWithSelector(api, ['selection', 'blockControls'], function (states) {
|
|
14
|
+
var _states$selectionStat, _states$blockControls;
|
|
15
|
+
return {
|
|
16
|
+
selection: (_states$selectionStat = states.selectionState) === null || _states$selectionStat === void 0 ? void 0 : _states$selectionStat.selection,
|
|
17
|
+
activeNode: (_states$blockControls = states.blockControlsState) === null || _states$blockControls === void 0 ? void 0 : _states$blockControls.activeNode
|
|
18
|
+
};
|
|
19
|
+
}),
|
|
20
|
+
selection = _useSharedPluginState.selection,
|
|
21
|
+
activeNode = _useSharedPluginState.activeNode;
|
|
22
|
+
var isNested = activeNode && activeNode.rootPos !== activeNode.pos;
|
|
23
|
+
var canBeConverted = useMemo(function () {
|
|
24
|
+
return selection && canBeConvertedToSyncBlock(selection);
|
|
25
|
+
}, [selection]);
|
|
26
|
+
if (isNested || !canBeConverted) {
|
|
16
27
|
return null;
|
|
17
28
|
}
|
|
18
29
|
var onClick = function onClick() {
|
|
@@ -30,7 +41,49 @@ export var CreateSyncedBlockDropdownItem = function CreateSyncedBlockDropdownIte
|
|
|
30
41
|
}, /*#__PURE__*/React.createElement(Flex, {
|
|
31
42
|
alignItems: "center",
|
|
32
43
|
gap: "space.050"
|
|
33
|
-
}, /*#__PURE__*/React.createElement(Text, null,
|
|
44
|
+
}, /*#__PURE__*/React.createElement(Text, null, formatMessage(blockMenuMessages.createSyncedBlock)), /*#__PURE__*/React.createElement(Lozenge, {
|
|
34
45
|
appearance: "new"
|
|
35
46
|
}, formatMessage(blockMenuMessages.newLozenge))));
|
|
47
|
+
};
|
|
48
|
+
var CopySyncedBlockDropdownItem = function CopySyncedBlockDropdownItem(_ref2) {
|
|
49
|
+
var api = _ref2.api;
|
|
50
|
+
var _useIntl2 = useIntl(),
|
|
51
|
+
formatMessage = _useIntl2.formatMessage;
|
|
52
|
+
var onClick = function onClick() {
|
|
53
|
+
var _api$core3, _api$core4, _api$blockControls2;
|
|
54
|
+
api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(api === null || api === void 0 ? void 0 : api.syncedBlock.commands.copySyncedBlockReferenceToClipboard());
|
|
55
|
+
api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.toggleBlockMenu({
|
|
56
|
+
closeMenu: true
|
|
57
|
+
}));
|
|
58
|
+
};
|
|
59
|
+
return /*#__PURE__*/React.createElement(ToolbarDropdownItem, {
|
|
60
|
+
elemBefore: /*#__PURE__*/React.createElement(SyncBlocksIcon, {
|
|
61
|
+
label: ""
|
|
62
|
+
}),
|
|
63
|
+
onClick: onClick
|
|
64
|
+
}, /*#__PURE__*/React.createElement(Flex, {
|
|
65
|
+
alignItems: "center",
|
|
66
|
+
gap: "space.050"
|
|
67
|
+
}, /*#__PURE__*/React.createElement(Text, null, formatMessage(blockMenuMessages.copySyncedBlock)), /*#__PURE__*/React.createElement(Lozenge, {
|
|
68
|
+
appearance: "new"
|
|
69
|
+
}, formatMessage(blockMenuMessages.newLozenge))));
|
|
70
|
+
};
|
|
71
|
+
export var CreateOrCopySyncedBlockDropdownItem = function CreateOrCopySyncedBlockDropdownItem(_ref3) {
|
|
72
|
+
var api = _ref3.api;
|
|
73
|
+
var _useSharedPluginState2 = useSharedPluginStateWithSelector(api, ['blockControls'], function (states) {
|
|
74
|
+
var _states$blockControls2;
|
|
75
|
+
return {
|
|
76
|
+
menuTriggerBy: (_states$blockControls2 = states.blockControlsState) === null || _states$blockControls2 === void 0 ? void 0 : _states$blockControls2.menuTriggerBy
|
|
77
|
+
};
|
|
78
|
+
}),
|
|
79
|
+
menuTriggerBy = _useSharedPluginState2.menuTriggerBy;
|
|
80
|
+
if (menuTriggerBy === 'syncBlock' || menuTriggerBy === 'bodiedSyncBlock') {
|
|
81
|
+
return /*#__PURE__*/React.createElement(CopySyncedBlockDropdownItem, {
|
|
82
|
+
api: api
|
|
83
|
+
});
|
|
84
|
+
} else {
|
|
85
|
+
return /*#__PURE__*/React.createElement(CreateSyncedBlockDropdownItem, {
|
|
86
|
+
api: api
|
|
87
|
+
});
|
|
88
|
+
}
|
|
36
89
|
};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { ADD_BLOCKS_MENU_SECTION, ADD_BLOCKS_MENU_SECTION_RANK, CREATE_SYNCED_BLOCK_MENU_ITEM } from '@atlaskit/editor-common/block-menu';
|
|
3
|
-
import {
|
|
3
|
+
import { CreateOrCopySyncedBlockDropdownItem } from './CreateSyncedBlockDropdownItem';
|
|
4
4
|
export var getBlockMenuComponents = function getBlockMenuComponents(api) {
|
|
5
5
|
return [{
|
|
6
6
|
type: 'block-menu-item',
|
|
@@ -11,7 +11,7 @@ export var getBlockMenuComponents = function getBlockMenuComponents(api) {
|
|
|
11
11
|
rank: ADD_BLOCKS_MENU_SECTION_RANK[CREATE_SYNCED_BLOCK_MENU_ITEM.key]
|
|
12
12
|
},
|
|
13
13
|
component: function component() {
|
|
14
|
-
return /*#__PURE__*/React.createElement(
|
|
14
|
+
return /*#__PURE__*/React.createElement(CreateOrCopySyncedBlockDropdownItem, {
|
|
15
15
|
api: api
|
|
16
16
|
});
|
|
17
17
|
}
|
|
@@ -12,7 +12,7 @@ import { copySyncedBlockReferenceToClipboard, editSyncedBlockSource, removeSynce
|
|
|
12
12
|
import { findSyncBlockOrBodiedSyncBlock, isBodiedSyncBlockNode } from '../pm-plugins/utils/utils';
|
|
13
13
|
export var getToolbarConfig = function getToolbarConfig(state, intl, api, syncBlockStore) {
|
|
14
14
|
var _api$decorations;
|
|
15
|
-
var syncBlockObject = findSyncBlockOrBodiedSyncBlock(state);
|
|
15
|
+
var syncBlockObject = findSyncBlockOrBodiedSyncBlock(state.schema, state.selection);
|
|
16
16
|
if (!syncBlockObject) {
|
|
17
17
|
return;
|
|
18
18
|
}
|
|
@@ -38,7 +38,7 @@ export var getToolbarConfig = function getToolbarConfig(state, intl, api, syncBl
|
|
|
38
38
|
title: formatMessage(messages.copySyncBlockLabel),
|
|
39
39
|
showTitle: false,
|
|
40
40
|
tooltipContent: formatMessage(messages.copySyncBlockTooltip),
|
|
41
|
-
onClick: copySyncedBlockReferenceToClipboard
|
|
41
|
+
onClick: copySyncedBlockReferenceToClipboard
|
|
42
42
|
}, hoverDecorationProps(nodeType, akEditorSelectedNodeClassName));
|
|
43
43
|
items.push(copyButton);
|
|
44
44
|
var disabled = !syncBlockStore.getSyncBlockURL(syncBlockObject.node.attrs.resourceId);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Command, ExtractInjectionAPI, TypeAheadInsert } from '@atlaskit/editor-common/types';
|
|
1
|
+
import type { Command, EditorCommand, ExtractInjectionAPI, TypeAheadInsert } from '@atlaskit/editor-common/types';
|
|
2
2
|
import { type Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
3
3
|
import type { SyncBlockStoreManager } from '@atlaskit/editor-synced-block-provider';
|
|
4
4
|
import type { SyncedBlockPlugin } from '../syncedBlockPluginType';
|
|
@@ -8,7 +8,8 @@ type createSyncedBlockProps = {
|
|
|
8
8
|
typeAheadInsert?: TypeAheadInsert;
|
|
9
9
|
};
|
|
10
10
|
export declare const createSyncedBlock: ({ tr, syncBlockStore, typeAheadInsert, }: createSyncedBlockProps) => false | Transaction;
|
|
11
|
-
export declare const
|
|
11
|
+
export declare const copySyncedBlockReferenceToClipboardEditorCommand: EditorCommand;
|
|
12
|
+
export declare const copySyncedBlockReferenceToClipboard: Command;
|
|
12
13
|
export declare const editSyncedBlockSource: (syncBlockStore: SyncBlockStoreManager, api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
|
|
13
14
|
export declare const removeSyncedBlock: (api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
|
|
14
15
|
export {};
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
-
import type { NodeType, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
-
import
|
|
2
|
+
import type { NodeType, Node as PMNode, Schema } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
import { type Selection } from '@atlaskit/editor-prosemirror/state';
|
|
4
4
|
import type { ContentNodeWithPos } from '@atlaskit/editor-prosemirror/utils';
|
|
5
|
-
export declare const findSyncBlock: (
|
|
6
|
-
export declare const findBodiedSyncBlock: (
|
|
7
|
-
export declare const findSyncBlockOrBodiedSyncBlock: (
|
|
5
|
+
export declare const findSyncBlock: (schema: Schema, selection: Selection) => ContentNodeWithPos | undefined;
|
|
6
|
+
export declare const findBodiedSyncBlock: (schema: Schema, selection: Selection) => ContentNodeWithPos | undefined;
|
|
7
|
+
export declare const findSyncBlockOrBodiedSyncBlock: (schema: Schema, selection: Selection) => ContentNodeWithPos | undefined;
|
|
8
8
|
export declare const isBodiedSyncBlockNode: (node: PMNode, bodiedSyncBlock: NodeType) => boolean;
|
|
9
9
|
export interface SyncBlockConversionInfo {
|
|
10
10
|
contentToInclude: Fragment;
|
|
11
11
|
from: number;
|
|
12
12
|
to: number;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Checks whether the selection can be converted to sync block
|
|
16
|
+
*
|
|
17
|
+
* @param selection - the current editor selection to validate for sync block conversion
|
|
18
|
+
* @returns A fragment containing the content to include in the synced block,
|
|
19
|
+
* stripping out unsupported marks (breakout on codeblock/expand/layout), as well as from and to positions,
|
|
20
|
+
* or false if conversion is not possible
|
|
21
|
+
*/
|
|
14
22
|
export declare const canBeConvertedToSyncBlock: (selection: Selection) => SyncBlockConversionInfo | false;
|
|
@@ -51,6 +51,7 @@ export type SyncedBlockPlugin = NextEditorPlugin<'syncedBlock', {
|
|
|
51
51
|
flushBodiedSyncBlocks: () => Promise<boolean>;
|
|
52
52
|
};
|
|
53
53
|
commands: {
|
|
54
|
+
copySyncedBlockReferenceToClipboard: () => EditorCommand;
|
|
54
55
|
insertSyncedBlock: () => EditorCommand;
|
|
55
56
|
};
|
|
56
57
|
dependencies: [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
3
3
|
import type { SyncedBlockPlugin } from '../syncedBlockPluginType';
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const CreateOrCopySyncedBlockDropdownItem: ({ api, }: {
|
|
5
5
|
api: ExtractInjectionAPI<SyncedBlockPlugin> | undefined;
|
|
6
|
-
}) => React.JSX.Element
|
|
6
|
+
}) => React.JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Command, ExtractInjectionAPI, TypeAheadInsert } from '@atlaskit/editor-common/types';
|
|
1
|
+
import type { Command, EditorCommand, ExtractInjectionAPI, TypeAheadInsert } from '@atlaskit/editor-common/types';
|
|
2
2
|
import { type Transaction } from '@atlaskit/editor-prosemirror/state';
|
|
3
3
|
import type { SyncBlockStoreManager } from '@atlaskit/editor-synced-block-provider';
|
|
4
4
|
import type { SyncedBlockPlugin } from '../syncedBlockPluginType';
|
|
@@ -8,7 +8,8 @@ type createSyncedBlockProps = {
|
|
|
8
8
|
typeAheadInsert?: TypeAheadInsert;
|
|
9
9
|
};
|
|
10
10
|
export declare const createSyncedBlock: ({ tr, syncBlockStore, typeAheadInsert, }: createSyncedBlockProps) => false | Transaction;
|
|
11
|
-
export declare const
|
|
11
|
+
export declare const copySyncedBlockReferenceToClipboardEditorCommand: EditorCommand;
|
|
12
|
+
export declare const copySyncedBlockReferenceToClipboard: Command;
|
|
12
13
|
export declare const editSyncedBlockSource: (syncBlockStore: SyncBlockStoreManager, api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
|
|
13
14
|
export declare const removeSyncedBlock: (api?: ExtractInjectionAPI<SyncedBlockPlugin>) => Command;
|
|
14
15
|
export {};
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import { Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
2
|
-
import type { NodeType, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
-
import
|
|
2
|
+
import type { NodeType, Node as PMNode, Schema } from '@atlaskit/editor-prosemirror/model';
|
|
3
|
+
import { type Selection } from '@atlaskit/editor-prosemirror/state';
|
|
4
4
|
import type { ContentNodeWithPos } from '@atlaskit/editor-prosemirror/utils';
|
|
5
|
-
export declare const findSyncBlock: (
|
|
6
|
-
export declare const findBodiedSyncBlock: (
|
|
7
|
-
export declare const findSyncBlockOrBodiedSyncBlock: (
|
|
5
|
+
export declare const findSyncBlock: (schema: Schema, selection: Selection) => ContentNodeWithPos | undefined;
|
|
6
|
+
export declare const findBodiedSyncBlock: (schema: Schema, selection: Selection) => ContentNodeWithPos | undefined;
|
|
7
|
+
export declare const findSyncBlockOrBodiedSyncBlock: (schema: Schema, selection: Selection) => ContentNodeWithPos | undefined;
|
|
8
8
|
export declare const isBodiedSyncBlockNode: (node: PMNode, bodiedSyncBlock: NodeType) => boolean;
|
|
9
9
|
export interface SyncBlockConversionInfo {
|
|
10
10
|
contentToInclude: Fragment;
|
|
11
11
|
from: number;
|
|
12
12
|
to: number;
|
|
13
13
|
}
|
|
14
|
+
/**
|
|
15
|
+
* Checks whether the selection can be converted to sync block
|
|
16
|
+
*
|
|
17
|
+
* @param selection - the current editor selection to validate for sync block conversion
|
|
18
|
+
* @returns A fragment containing the content to include in the synced block,
|
|
19
|
+
* stripping out unsupported marks (breakout on codeblock/expand/layout), as well as from and to positions,
|
|
20
|
+
* or false if conversion is not possible
|
|
21
|
+
*/
|
|
14
22
|
export declare const canBeConvertedToSyncBlock: (selection: Selection) => SyncBlockConversionInfo | false;
|
|
@@ -51,6 +51,7 @@ export type SyncedBlockPlugin = NextEditorPlugin<'syncedBlock', {
|
|
|
51
51
|
flushBodiedSyncBlocks: () => Promise<boolean>;
|
|
52
52
|
};
|
|
53
53
|
commands: {
|
|
54
|
+
copySyncedBlockReferenceToClipboard: () => EditorCommand;
|
|
54
55
|
insertSyncedBlock: () => EditorCommand;
|
|
55
56
|
};
|
|
56
57
|
dependencies: [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import type { ExtractInjectionAPI } from '@atlaskit/editor-common/types';
|
|
3
3
|
import type { SyncedBlockPlugin } from '../syncedBlockPluginType';
|
|
4
|
-
export declare const
|
|
4
|
+
export declare const CreateOrCopySyncedBlockDropdownItem: ({ api, }: {
|
|
5
5
|
api: ExtractInjectionAPI<SyncedBlockPlugin> | undefined;
|
|
6
|
-
}) => React.JSX.Element
|
|
6
|
+
}) => React.JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@atlaskit/editor-plugin-synced-block",
|
|
3
|
-
"version": "4.2.
|
|
3
|
+
"version": "4.2.3",
|
|
4
4
|
"description": "SyncedBlock plugin for @atlaskit/editor-core",
|
|
5
5
|
"author": "Atlassian Pty Ltd",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -37,12 +37,12 @@
|
|
|
37
37
|
"@atlaskit/editor-plugin-floating-toolbar": "^8.2.0",
|
|
38
38
|
"@atlaskit/editor-plugin-selection": "^6.1.0",
|
|
39
39
|
"@atlaskit/editor-prosemirror": "7.0.0",
|
|
40
|
-
"@atlaskit/editor-shared-styles": "^3.
|
|
40
|
+
"@atlaskit/editor-shared-styles": "^3.9.0",
|
|
41
41
|
"@atlaskit/editor-synced-block-provider": "^2.7.0",
|
|
42
42
|
"@atlaskit/editor-tables": "^2.9.0",
|
|
43
43
|
"@atlaskit/editor-toolbar": "^0.17.0",
|
|
44
44
|
"@atlaskit/icon": "28.5.4",
|
|
45
|
-
"@atlaskit/icon-lab": "^5.
|
|
45
|
+
"@atlaskit/icon-lab": "^5.12.0",
|
|
46
46
|
"@atlaskit/logo": "^19.9.0",
|
|
47
47
|
"@atlaskit/lozenge": "^13.1.0",
|
|
48
48
|
"@atlaskit/modal-dialog": "^14.6.0",
|
|
@@ -53,7 +53,7 @@
|
|
|
53
53
|
"react-intl-next": "npm:react-intl@^5.18.1"
|
|
54
54
|
},
|
|
55
55
|
"peerDependencies": {
|
|
56
|
-
"@atlaskit/editor-common": "^110.
|
|
56
|
+
"@atlaskit/editor-common": "^110.27.0",
|
|
57
57
|
"react": "^18.2.0"
|
|
58
58
|
},
|
|
59
59
|
"devDependencies": {
|