@atlaskit/editor-plugin-synced-block 12.0.5 → 12.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +14 -0
- package/dist/cjs/editor-commands/index.js +8 -18
- package/dist/cjs/nodeviews/bodiedSyncedBlock.js +3 -7
- package/dist/cjs/nodeviews/syncedBlock.js +9 -15
- package/dist/cjs/pm-plugins/main.js +14 -42
- package/dist/cjs/pm-plugins/utils/handle-bodied-sync-block-removal.js +36 -54
- package/dist/cjs/syncedBlockPlugin.js +1 -4
- package/dist/cjs/ui/CreateSyncedBlockButton.js +23 -35
- package/dist/cjs/ui/CreateSyncedBlockDropdownItem.js +36 -47
- package/dist/cjs/ui/SyncBlockLabel.js +2 -13
- package/dist/cjs/ui/SyncBlockRendererWrapper.js +7 -9
- package/dist/cjs/ui/SyncedLocationDropdown.js +53 -116
- package/dist/cjs/ui/floating-toolbar.js +1 -2
- package/dist/es2019/editor-commands/index.js +8 -18
- package/dist/es2019/nodeviews/bodiedSyncedBlock.js +3 -7
- package/dist/es2019/nodeviews/syncedBlock.js +9 -15
- package/dist/es2019/pm-plugins/main.js +16 -41
- package/dist/es2019/pm-plugins/utils/handle-bodied-sync-block-removal.js +33 -51
- package/dist/es2019/syncedBlockPlugin.js +1 -4
- package/dist/es2019/ui/CreateSyncedBlockButton.js +25 -36
- package/dist/es2019/ui/CreateSyncedBlockDropdownItem.js +36 -47
- package/dist/es2019/ui/SyncBlockLabel.js +2 -13
- package/dist/es2019/ui/SyncBlockRendererWrapper.js +7 -9
- package/dist/es2019/ui/SyncedLocationDropdown.js +1 -58
- package/dist/es2019/ui/floating-toolbar.js +1 -2
- package/dist/esm/editor-commands/index.js +8 -18
- package/dist/esm/nodeviews/bodiedSyncedBlock.js +3 -7
- package/dist/esm/nodeviews/syncedBlock.js +9 -15
- package/dist/esm/pm-plugins/main.js +15 -43
- package/dist/esm/pm-plugins/utils/handle-bodied-sync-block-removal.js +36 -54
- package/dist/esm/syncedBlockPlugin.js +1 -4
- package/dist/esm/ui/CreateSyncedBlockButton.js +23 -35
- package/dist/esm/ui/CreateSyncedBlockDropdownItem.js +36 -47
- package/dist/esm/ui/SyncBlockLabel.js +2 -13
- package/dist/esm/ui/SyncBlockRendererWrapper.js +7 -9
- package/dist/esm/ui/SyncedLocationDropdown.js +53 -116
- package/dist/esm/ui/floating-toolbar.js +1 -2
- package/dist/types/pm-plugins/main.d.ts +2 -4
- package/package.json +5 -14
|
@@ -11,7 +11,6 @@ import DeleteIcon from '@atlaskit/icon/core/delete';
|
|
|
11
11
|
import EditIcon from '@atlaskit/icon/core/edit';
|
|
12
12
|
import LinkBrokenIcon from '@atlaskit/icon/core/link-broken';
|
|
13
13
|
import MegaphoneIcon from '@atlaskit/icon/core/megaphone';
|
|
14
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
15
14
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
16
15
|
import { copySyncedBlockReferenceToClipboard, editSyncedBlockSource, removeSyncedBlock, unsync } from '../editor-commands';
|
|
17
16
|
import { findSyncBlockOrBodiedSyncBlock, isBodiedSyncBlockNode } from '../pm-plugins/utils/utils';
|
|
@@ -158,7 +157,7 @@ export const getToolbarConfig = (state, intl, api, syncBlockStore, isLivePage, o
|
|
|
158
157
|
};
|
|
159
158
|
items.push(editSourceButton);
|
|
160
159
|
}
|
|
161
|
-
if (!isSyncBlockActivationEnabled
|
|
160
|
+
if (!isSyncBlockActivationEnabled) {
|
|
162
161
|
const separator = {
|
|
163
162
|
type: 'separator'
|
|
164
163
|
};
|
|
@@ -8,7 +8,6 @@ import { DOMSerializer, Fragment } from '@atlaskit/editor-prosemirror/model';
|
|
|
8
8
|
import { NodeSelection, Selection, TextSelection } from '@atlaskit/editor-prosemirror/state';
|
|
9
9
|
import { findSelectedNodeOfType, removeParentNodeOfType, removeSelectedNode, safeInsert } from '@atlaskit/editor-prosemirror/utils';
|
|
10
10
|
import { getSourceProductFromResourceIdSafe } from '@atlaskit/editor-synced-block-provider/utils';
|
|
11
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
12
11
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
13
12
|
import { creationMetaKey, deleteMechanismMetaKey, syncedBlockPluginKey } from '../pm-plugins/main';
|
|
14
13
|
import { canBeConvertedToSyncBlock, deferDispatch, findSyncBlock, findSyncBlockOrBodiedSyncBlock, isBodiedSyncBlockNode } from '../pm-plugins/utils/utils';
|
|
@@ -108,9 +107,7 @@ export var createSyncedBlock = function createSyncedBlock(_ref) {
|
|
|
108
107
|
// safeInsert does not move the selection into the new block, so place the
|
|
109
108
|
// caret inside the block's empty paragraph so typing continues inside the
|
|
110
109
|
// synced block (EDITOR-7949).
|
|
111
|
-
|
|
112
|
-
tr = placeCaretInsideBodiedSyncBlock(tr, newBodiedSyncBlockNode.attrs.localId);
|
|
113
|
-
}
|
|
110
|
+
tr = placeCaretInsideBodiedSyncBlock(tr, newBodiedSyncBlockNode.attrs.localId);
|
|
114
111
|
}
|
|
115
112
|
} else {
|
|
116
113
|
var conversionInfo = canBeConvertedToSyncBlock(tr.selection);
|
|
@@ -141,14 +138,10 @@ export var createSyncedBlock = function createSyncedBlock(_ref) {
|
|
|
141
138
|
return false;
|
|
142
139
|
}
|
|
143
140
|
tr.replaceWith(conversionInfo.from, conversionInfo.to, _newBodiedSyncBlockNode).scrollIntoView();
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
} else {
|
|
149
|
-
// set selection to the start of the previous selection for the position taken up by the start of the new synced block
|
|
150
|
-
tr.setSelection(TextSelection.create(tr.doc, conversionInfo.from));
|
|
151
|
-
}
|
|
141
|
+
|
|
142
|
+
// Place the caret on the first editable position inside the converted
|
|
143
|
+
// content so typing continues inside the synced block (EDITOR-7949).
|
|
144
|
+
tr = placeCaretInsideBodiedSyncBlock(tr, _newBodiedSyncBlockNode.attrs.localId);
|
|
152
145
|
}
|
|
153
146
|
|
|
154
147
|
// Stash creation-type signals on the final transaction (after any typeahead
|
|
@@ -252,7 +245,7 @@ var copySyncedBlockReferenceToClipboardInternal = function copySyncedBlockRefere
|
|
|
252
245
|
attributes: _objectSpread({
|
|
253
246
|
resourceId: referenceSyncBlockNode.attrs.resourceId,
|
|
254
247
|
inputMethod: inputMethod
|
|
255
|
-
}, sourceJoinKey &&
|
|
248
|
+
}, sourceJoinKey && {
|
|
256
249
|
blockInstanceId: sourceJoinKey
|
|
257
250
|
})
|
|
258
251
|
});
|
|
@@ -333,11 +326,8 @@ export var removeSyncedBlock = function removeSyncedBlock(api) {
|
|
|
333
326
|
}
|
|
334
327
|
|
|
335
328
|
// Tag the transaction so analytics can report this as `deleteButton` rather
|
|
336
|
-
// than a keyboard delete (both produce a plain ReplaceStep).
|
|
337
|
-
|
|
338
|
-
if (fg('platform_editor_blocks_patch_4')) {
|
|
339
|
-
removeTr.setMeta(deleteMechanismMetaKey, 'deleteButton');
|
|
340
|
-
}
|
|
329
|
+
// than a keyboard delete (both produce a plain ReplaceStep).
|
|
330
|
+
removeTr.setMeta(deleteMechanismMetaKey, 'deleteButton');
|
|
341
331
|
dispatch(removeTr);
|
|
342
332
|
api === null || api === void 0 || api.core.actions.focus();
|
|
343
333
|
return true;
|
|
@@ -7,7 +7,6 @@ import { ErrorBoundary } from '@atlaskit/editor-common/error-boundary';
|
|
|
7
7
|
import { BodiedSyncBlockSharedCssClassName } from '@atlaskit/editor-common/sync-block';
|
|
8
8
|
import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity';
|
|
9
9
|
import { DOMSerializer } from '@atlaskit/editor-prosemirror/model';
|
|
10
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
11
10
|
import { SyncBlockLabel } from '../ui/SyncBlockLabel';
|
|
12
11
|
import { isEmptySourceSyncBlock } from './isEmptySourceSyncBlock';
|
|
13
12
|
var toDOM = function toDOM(node) {
|
|
@@ -44,15 +43,12 @@ export var BodiedSyncBlock = /*#__PURE__*/function () {
|
|
|
44
43
|
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage -- NodeView DOM must be created against active runtime document
|
|
45
44
|
labelContainer = document.createElement('div');
|
|
46
45
|
this.dom.appendChild(labelContainer);
|
|
47
|
-
} else
|
|
48
|
-
// Render the label into a separate container
|
|
49
|
-
//
|
|
50
|
-
// the ProseMirror contentDOM.
|
|
46
|
+
} else {
|
|
47
|
+
// Render the label into a separate container so portal implementations
|
|
48
|
+
// that write directly into the target do not clobber contentDOM.
|
|
51
49
|
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage -- NodeView DOM must be created against active runtime document
|
|
52
50
|
labelContainer = document.createElement('div');
|
|
53
51
|
this.dom.appendChild(labelContainer);
|
|
54
|
-
} else {
|
|
55
|
-
labelContainer = this.dom;
|
|
56
52
|
}
|
|
57
53
|
this.labelKey = crypto.randomUUID();
|
|
58
54
|
this.nodeViewPortalProviderAPI.render(function () {
|
|
@@ -14,7 +14,6 @@ import { ErrorBoundary } from '@atlaskit/editor-common/error-boundary';
|
|
|
14
14
|
import ReactNodeView from '@atlaskit/editor-common/react-node-view';
|
|
15
15
|
import { SyncBlockSharedCssClassName, SyncBlockLabelSharedCssClassName, SyncBlockActionsProvider } from '@atlaskit/editor-common/sync-block';
|
|
16
16
|
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
17
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
18
17
|
import { removeSyncedBlockAtPos } from '../editor-commands';
|
|
19
18
|
import { SyncBlockRendererWrapper } from '../ui/SyncBlockRendererWrapper';
|
|
20
19
|
import { SyncBlockSSRReactContextsProvider } from '../ui/SyncBlockSSRReactContextsProvider';
|
|
@@ -62,17 +61,15 @@ export var SyncBlock = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
62
61
|
// eslint-disable-next-line @atlaskit/platform/no-direct-document-usage -- NodeView DOM must be created against active runtime document
|
|
63
62
|
var domRef = document.createElement('div');
|
|
64
63
|
domRef.classList.add(SyncBlockSharedCssClassName.prefix);
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
domRef.addEventListener('dragstart', this.dragStartHandler);
|
|
75
|
-
}
|
|
64
|
+
// Prevent native browser drag on the contentEditable="false" wrapper.
|
|
65
|
+
// Without this, clicking in empty space (outside the contentEditable
|
|
66
|
+
// renderer but inside the domRef) initiates a native element drag.
|
|
67
|
+
domRef.draggable = false;
|
|
68
|
+
this.dragStartHandler = function (e) {
|
|
69
|
+
e.preventDefault();
|
|
70
|
+
};
|
|
71
|
+
// eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop, @repo/internal/dom-events/no-unsafe-event-listeners
|
|
72
|
+
domRef.addEventListener('dragstart', this.dragStartHandler);
|
|
76
73
|
return domRef;
|
|
77
74
|
}
|
|
78
75
|
|
|
@@ -105,9 +102,6 @@ export var SyncBlock = /*#__PURE__*/function (_ReactNodeView) {
|
|
|
105
102
|
}, {
|
|
106
103
|
key: "stopEvent",
|
|
107
104
|
value: function stopEvent(event) {
|
|
108
|
-
if (!fg('platform_synced_block_patch_14')) {
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
105
|
var target = event.target;
|
|
112
106
|
if (!(target instanceof Element)) {
|
|
113
107
|
return false;
|
|
@@ -18,9 +18,8 @@ import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity';
|
|
|
18
18
|
import { NodeSelection, PluginKey } from '@atlaskit/editor-prosemirror/state';
|
|
19
19
|
import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
|
|
20
20
|
import { DecorationSet, Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
21
|
-
import { convertPMNodesToSyncBlockNodes
|
|
21
|
+
import { convertPMNodesToSyncBlockNodes } from '@atlaskit/editor-synced-block-provider';
|
|
22
22
|
import { getSourceProductFromResourceIdSafe } from '@atlaskit/editor-synced-block-provider/utils';
|
|
23
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
24
23
|
import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
|
|
25
24
|
import { bodiedSyncBlockNodeView } from '../nodeviews/bodiedSyncedBlock';
|
|
26
25
|
import { SyncBlock as SyncBlockView } from '../nodeviews/syncedBlock';
|
|
@@ -41,8 +40,7 @@ export var syncedBlockPluginKey = new PluginKey('syncedBlockPlugin');
|
|
|
41
40
|
* `deleteButton` (otherwise indistinguishable from a keyboard delete — both are
|
|
42
41
|
* plain ReplaceSteps). A separate key (rather than `syncedBlockPluginKey`, which
|
|
43
42
|
* carries plugin-state transitions read in `apply()`, or a bare string) keeps
|
|
44
|
-
* this transient signal uniquely namespaced and isolated.
|
|
45
|
-
* `platform_editor_blocks_patch_4`.
|
|
43
|
+
* this transient signal uniquely namespaced and isolated.
|
|
46
44
|
*/
|
|
47
45
|
export var deleteMechanismMetaKey = new PluginKey('syncedBlockDeleteMechanism');
|
|
48
46
|
var syncedBlockPromptedFeedbackMetaKey = new PluginKey('syncedBlockPromptedFeedback');
|
|
@@ -51,8 +49,7 @@ var syncedBlockPromptedFeedbackMetaKey = new PluginKey('syncedBlockPromptedFeedb
|
|
|
51
49
|
* Creation-type signals set by {@link createSyncedBlock} on the creating
|
|
52
50
|
* transaction. The async creation handler forwards them to the store manager,
|
|
53
51
|
* which attaches them to the `syncedBlockCreate` event. A dedicated key keeps
|
|
54
|
-
* this transient signal isolated from plugin state.
|
|
55
|
-
* `platform_editor_blocks_patch_4`.
|
|
52
|
+
* this transient signal isolated from plugin state.
|
|
56
53
|
*/
|
|
57
54
|
|
|
58
55
|
export var creationMetaKey = new PluginKey('syncedBlockCreationMeta');
|
|
@@ -308,17 +305,9 @@ var filterTransactionOnline = function filterTransactionOnline(_ref3) {
|
|
|
308
305
|
});
|
|
309
306
|
});
|
|
310
307
|
if (bodiedSyncBlockRemoved.length > 0) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
// platform_editor_blocks_patch_4 is on we instead recompute the delete fresh
|
|
315
|
-
// from the live document on confirm (see handleBodiedSyncBlockRemoval), so
|
|
316
|
-
// there is no need to stash the transaction here. See EDITOR-7889.
|
|
317
|
-
// eslint-disable-next-line no-param-reassign
|
|
318
|
-
confirmationTransactionRef.current = tr;
|
|
319
|
-
}
|
|
320
|
-
// Only derive the mechanism behind the gate — discarded gate-off.
|
|
321
|
-
var mechanism = fg('platform_editor_blocks_patch_4') ? getDeleteMechanism(tr, state) : undefined;
|
|
308
|
+
// Recompute the delete fresh from the live document on confirm
|
|
309
|
+
// (see handleBodiedSyncBlockRemoval). See EDITOR-7889.
|
|
310
|
+
var mechanism = getDeleteMechanism(tr, state);
|
|
322
311
|
var feedbackContext = entryPoint && getDeleteReason(tr) !== 'source-block-unsynced' ? {
|
|
323
312
|
blockType: 'source',
|
|
324
313
|
entryPoint: entryPoint
|
|
@@ -356,7 +345,7 @@ var filterTransactionOnline = function filterTransactionOnline(_ref3) {
|
|
|
356
345
|
// be wrong. The bodiedSyncBlock content will still be inserted but will
|
|
357
346
|
// not be registered as a source block in Block Service, which is safer
|
|
358
347
|
// than creating a zombie block under the wrong ARI.
|
|
359
|
-
if (isPasteOrDrop
|
|
348
|
+
if (isPasteOrDrop) {
|
|
360
349
|
return true;
|
|
361
350
|
}
|
|
362
351
|
|
|
@@ -690,8 +679,8 @@ export var createPlugin = function createPlugin(options, pmPluginFactoryParams,
|
|
|
690
679
|
var syncBlockNodes = instance.doc.children.filter(syncBlockStore.referenceManager.isReferenceBlock);
|
|
691
680
|
syncBlockStore.referenceManager.fetchSyncBlocksData(convertPMNodesToSyncBlockNodes(syncBlockNodes));
|
|
692
681
|
|
|
693
|
-
// Populate source sync block cache from initial document
|
|
694
|
-
//
|
|
682
|
+
// Populate source sync block cache from initial document.
|
|
683
|
+
// This replaces the constructor call in the nodeview.
|
|
695
684
|
instance.doc.forEach(function (node) {
|
|
696
685
|
if (syncBlockStore.sourceManager.isSourceBlock(node)) {
|
|
697
686
|
syncBlockStore.sourceManager.updateSyncBlockData(node, false);
|
|
@@ -923,18 +912,12 @@ export var createPlugin = function createPlugin(options, pmPluginFactoryParams,
|
|
|
923
912
|
return false;
|
|
924
913
|
},
|
|
925
914
|
cut: function cut() {
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
ctx.markCutEvent();
|
|
929
|
-
}
|
|
915
|
+
ctx.consumeCutEvent();
|
|
916
|
+
ctx.markCutEvent();
|
|
930
917
|
return false;
|
|
931
918
|
}
|
|
932
919
|
},
|
|
933
920
|
transformPasted: function transformPasted(slice, _view) {
|
|
934
|
-
if (!fg('platform_synced_block_patch_13')) {
|
|
935
|
-
return slice;
|
|
936
|
-
}
|
|
937
|
-
|
|
938
921
|
// Defense against bodiedSyncBlock nodes arriving via paste
|
|
939
922
|
// (e.g. drag-and-drop, cut-paste, or browser-level clipboard
|
|
940
923
|
// operations that bypass the transformCopied handler).
|
|
@@ -960,9 +943,8 @@ export var createPlugin = function createPlugin(options, pmPluginFactoryParams,
|
|
|
960
943
|
var syncBlockStore = pluginState === null || pluginState === void 0 ? void 0 : pluginState.syncBlockStore;
|
|
961
944
|
var schema = state.schema;
|
|
962
945
|
var isCopy = ctx.consumeCopyEvent();
|
|
963
|
-
var isSyncedBlockPatch13Enabled = fg('platform_synced_block_patch_13');
|
|
964
946
|
var wasCut = ctx.consumeCutEvent();
|
|
965
|
-
var isCut =
|
|
947
|
+
var isCut = wasCut;
|
|
966
948
|
var isPromptedFeedbackCut = Boolean(syncBlockStore && (options === null || options === void 0 ? void 0 : options.onGiveFeedback) && wasCut) && expValEqualsNoExposure('platform_editor_sync_block_activation', 'isEnabled', true);
|
|
967
949
|
if (!syncBlockStore || !isCopy && !isCut && !isPromptedFeedbackCut) {
|
|
968
950
|
return slice;
|
|
@@ -1000,7 +982,7 @@ export var createPlugin = function createPlugin(options, pmPluginFactoryParams,
|
|
|
1000
982
|
if (!sliceFullyContainsNode(slice, node)) {
|
|
1001
983
|
return node.content;
|
|
1002
984
|
}
|
|
1003
|
-
if (
|
|
985
|
+
if (isCut) {
|
|
1004
986
|
return node;
|
|
1005
987
|
}
|
|
1006
988
|
var newResourceId = syncBlockStore.referenceManager.generateResourceIdForReference(node.attrs.resourceId);
|
|
@@ -1157,18 +1139,8 @@ export var createPlugin = function createPlugin(options, pmPluginFactoryParams,
|
|
|
1157
1139
|
});
|
|
1158
1140
|
}
|
|
1159
1141
|
|
|
1160
|
-
//
|
|
1161
|
-
//
|
|
1162
|
-
// no stashed transaction to rebase here. See EDITOR-7889.
|
|
1163
|
-
if (!fg('platform_editor_blocks_patch_4')) {
|
|
1164
|
-
trs.filter(function (tr) {
|
|
1165
|
-
return tr.docChanged;
|
|
1166
|
-
}).forEach(function (tr) {
|
|
1167
|
-
if (confirmationTransactionRef.current) {
|
|
1168
|
-
confirmationTransactionRef.current = rebaseTransaction(confirmationTransactionRef.current, tr, newState);
|
|
1169
|
-
}
|
|
1170
|
-
});
|
|
1171
|
-
}
|
|
1142
|
+
// Delete is recomputed fresh from the live document on confirm.
|
|
1143
|
+
// See EDITOR-7889.
|
|
1172
1144
|
var _iterator2 = _createForOfIteratorHelper(trs),
|
|
1173
1145
|
_step2;
|
|
1174
1146
|
try {
|
|
@@ -38,67 +38,49 @@ export var handleBodiedSyncBlockRemoval = function handleBodiedSyncBlockRemoval(
|
|
|
38
38
|
syncBlockStore.sourceManager.deleteSyncBlocksWithConfirmation(bodiedSyncBlockRemoved.map(function (node) {
|
|
39
39
|
return node.attrs;
|
|
40
40
|
}), deletionReason, function () {
|
|
41
|
-
var _api$
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
return node.attrs;
|
|
62
|
-
}));
|
|
41
|
+
var _api$core2;
|
|
42
|
+
// Recompute the delete fresh from the live document instead of
|
|
43
|
+
// replaying a stashed-and-rebased transaction. The stash/rebase
|
|
44
|
+
// approach produced stale, schema-invalid transactions when the
|
|
45
|
+
// document changed shape (local edits or remote collab) while the
|
|
46
|
+
// confirmation modal was open — the dominant signature being
|
|
47
|
+
// "Invalid content for node bodiedSyncBlock: <>". See EDITOR-7889.
|
|
48
|
+
api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref2) {
|
|
49
|
+
var tr = _ref2.tr;
|
|
50
|
+
// EDITOR-8230: unsync must remove only the sync wrapper and keep the block's
|
|
51
|
+
// content inline, whereas delete removes the whole block. Before this branch,
|
|
52
|
+
// the confirm path always recomputed a full delete, so unsyncing a source block
|
|
53
|
+
// silently deleted its content. When the deletion was actually triggered by
|
|
54
|
+
// unsync, recompute an unwrap (replaceWith content) instead of a delete.
|
|
55
|
+
var isUnsync = fg('platform_editor_blocks_patch_6') && deletionReason === 'source-block-unsynced';
|
|
56
|
+
var recomputedTr = isUnsync ? recomputeUnsyncTransaction(tr, syncBlockStore.sourceManager.isSourceBlock, bodiedSyncBlockRemoved.map(function (node) {
|
|
57
|
+
return node.attrs;
|
|
58
|
+
})) : recomputeDeleteTransaction(tr, syncBlockStore.sourceManager.isSourceBlock, bodiedSyncBlockRemoved.map(function (node) {
|
|
59
|
+
return node.attrs;
|
|
60
|
+
}));
|
|
63
61
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
// bodiedSyncBlock deletion is expected to be permanent (cannot undo)
|
|
77
|
-
// For a normal deletion (not triggered by undo), remove it from history so that it cannot be undone
|
|
78
|
-
recomputedTr.setMeta('addToHistory', false);
|
|
79
|
-
}
|
|
80
|
-
return recomputedTr;
|
|
81
|
-
});
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
var confirmationTransaction = confirmationTransactionRef.current;
|
|
85
|
-
if (!confirmationTransaction) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function () {
|
|
89
|
-
var trToDispatch = confirmationTransaction.setMeta('isConfirmedSyncBlockDeletion', true);
|
|
90
|
-
feedbackCallbacks === null || feedbackCallbacks === void 0 || feedbackCallbacks.onDeleteTransaction(trToDispatch);
|
|
91
|
-
if (!trToDispatch.getMeta(pmHistoryPluginKey)) {
|
|
62
|
+
// The target node(s) no longer exist in the live document (e.g.
|
|
63
|
+
// a remote collaborator already removed them). There is nothing
|
|
64
|
+
// to delete locally, so return `null` to skip the dispatch
|
|
65
|
+
// entirely — dispatching the untouched transaction would be a
|
|
66
|
+
// no-op that still runs the plugin's filter/append hooks. The
|
|
67
|
+
// backend deletion has already been issued by the store manager.
|
|
68
|
+
if (!recomputedTr) {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
recomputedTr.setMeta('isConfirmedSyncBlockDeletion', true);
|
|
72
|
+
feedbackCallbacks === null || feedbackCallbacks === void 0 || feedbackCallbacks.onDeleteTransaction(recomputedTr);
|
|
73
|
+
if (!recomputedTr.getMeta(pmHistoryPluginKey)) {
|
|
92
74
|
// bodiedSyncBlock deletion is expected to be permanent (cannot undo)
|
|
93
75
|
// For a normal deletion (not triggered by undo), remove it from history so that it cannot be undone
|
|
94
|
-
|
|
76
|
+
recomputedTr.setMeta('addToHistory', false);
|
|
95
77
|
}
|
|
96
|
-
return
|
|
78
|
+
return recomputedTr;
|
|
97
79
|
});
|
|
98
80
|
}, function (success) {
|
|
99
|
-
var _api$
|
|
81
|
+
var _api$core3;
|
|
100
82
|
feedbackCallbacks === null || feedbackCallbacks === void 0 || feedbackCallbacks.onDeleteCompleted(success);
|
|
101
|
-
api === null || api === void 0 || (_api$
|
|
83
|
+
api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref3) {
|
|
102
84
|
var tr = _ref3.tr;
|
|
103
85
|
var newState;
|
|
104
86
|
if (!success) {
|
|
@@ -2,7 +2,6 @@ import React from 'react';
|
|
|
2
2
|
import { syncBlock, bodiedSyncBlock } from '@atlaskit/adf-schema';
|
|
3
3
|
import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
|
|
4
4
|
import { SyncBlockStoreManager } from '@atlaskit/editor-synced-block-provider';
|
|
5
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
6
5
|
import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
|
|
7
6
|
import { flushBodiedSyncBlocks as _flushBodiedSyncBlocks, flushSyncBlocks, discardUnpublishedSyncBlocks as _discardUnpublishedSyncBlocks } from './editor-actions';
|
|
8
7
|
import { copySyncedBlockReferenceToClipboardEditorCommand, createSyncedBlock } from './editor-commands';
|
|
@@ -189,9 +188,7 @@ export var syncedBlockPlugin = function syncedBlockPlugin(_ref2) {
|
|
|
189
188
|
// Destroy the SyncBlockStoreManager on editor unmount to cancel
|
|
190
189
|
// pending timers, subscriptions, and in-flight fetches.
|
|
191
190
|
destroy: function destroy() {
|
|
192
|
-
|
|
193
|
-
syncBlockStore.destroy();
|
|
194
|
-
}
|
|
191
|
+
syncBlockStore.destroy();
|
|
195
192
|
}
|
|
196
193
|
};
|
|
197
194
|
};
|
|
@@ -6,7 +6,6 @@ import { syncBlockMessages } from '@atlaskit/editor-common/messages';
|
|
|
6
6
|
import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity';
|
|
7
7
|
import { ToolbarButton, ToolbarTooltip } from '@atlaskit/editor-toolbar';
|
|
8
8
|
import BlockSyncedIcon from '@atlaskit/icon-lab/core/block-synced';
|
|
9
|
-
import { fg } from '@atlaskit/platform-feature-flags';
|
|
10
9
|
import { canBeConvertedToSyncBlock } from '../pm-plugins/utils/utils';
|
|
11
10
|
import { SYNCED_BLOCK_BUTTON_TEST_ID } from '../types';
|
|
12
11
|
export var CreateSyncedBlockButton = function CreateSyncedBlockButton(_ref) {
|
|
@@ -28,45 +27,34 @@ export var CreateSyncedBlockButton = function CreateSyncedBlockButton(_ref) {
|
|
|
28
27
|
var canInsertEmptyBlock = Boolean(selection === null || selection === void 0 ? void 0 : selection.empty);
|
|
29
28
|
var isDisabled = Boolean(isOfflineMode(mode) || !canBeConverted && !canInsertEmptyBlock);
|
|
30
29
|
var onClick = useCallback(function () {
|
|
31
|
-
var _api$
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
var
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
var result = api === null || api === void 0 ? void 0 : api.syncedBlock.commands.insertSyncedBlock(INPUT_METHOD.SYNCED_BLOCK_TB)({
|
|
47
|
-
tr: tr
|
|
48
|
-
});
|
|
49
|
-
if (!result) {
|
|
50
|
-
return null;
|
|
51
|
-
}
|
|
52
|
-
api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.commands) === null || _api$blockControls === void 0 || _api$blockControls.stopPreservingSelection()({
|
|
53
|
-
tr: tr
|
|
54
|
-
});
|
|
55
|
-
return tr;
|
|
30
|
+
var _api$core;
|
|
31
|
+
// Insert the synced block and stop preserving the selection in a single
|
|
32
|
+
// transaction so the caret that insertSyncedBlock places inside the new
|
|
33
|
+
// block survives (EDITOR-7949). The toolbar is not normally opened via the
|
|
34
|
+
// block menu, but stopping preservation is defensive and keeps behaviour
|
|
35
|
+
// consistent with the block-menu create item should preservation ever be
|
|
36
|
+
// active (e.g. a block is selected via block-controls). Then re-focus so
|
|
37
|
+
// the caret is active, but only when the transaction was actually
|
|
38
|
+
// dispatched — otherwise a failed insertion would still steal DOM focus
|
|
39
|
+
// into the editor (mirrors CreateSyncedBlockDropdownItem).
|
|
40
|
+
var dispatched = api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(function (_ref2) {
|
|
41
|
+
var _api$blockControls;
|
|
42
|
+
var tr = _ref2.tr;
|
|
43
|
+
var result = api === null || api === void 0 ? void 0 : api.syncedBlock.commands.insertSyncedBlock(INPUT_METHOD.SYNCED_BLOCK_TB)({
|
|
44
|
+
tr: tr
|
|
56
45
|
});
|
|
57
|
-
if (
|
|
58
|
-
|
|
59
|
-
api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.focus();
|
|
46
|
+
if (!result) {
|
|
47
|
+
return null;
|
|
60
48
|
}
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(function (_ref3) {
|
|
64
|
-
var tr = _ref3.tr;
|
|
65
|
-
return api === null || api === void 0 ? void 0 : api.syncedBlock.commands.insertSyncedBlock(INPUT_METHOD.SYNCED_BLOCK_TB)({
|
|
49
|
+
api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.commands) === null || _api$blockControls === void 0 || _api$blockControls.stopPreservingSelection()({
|
|
66
50
|
tr: tr
|
|
67
51
|
});
|
|
52
|
+
return tr;
|
|
68
53
|
});
|
|
69
|
-
|
|
54
|
+
if (dispatched) {
|
|
55
|
+
var _api$core2;
|
|
56
|
+
api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.focus();
|
|
57
|
+
}
|
|
70
58
|
}, [api]);
|
|
71
59
|
var message = intl.formatMessage(syncBlockMessages.syncBlockLabel);
|
|
72
60
|
return /*#__PURE__*/React.createElement(ToolbarTooltip, {
|
|
@@ -39,53 +39,42 @@ var CreateSyncedBlockDropdownItem = function CreateSyncedBlockDropdownItem(_ref2
|
|
|
39
39
|
return null;
|
|
40
40
|
}
|
|
41
41
|
var onClick = function onClick() {
|
|
42
|
-
var _api$
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
var
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
var result = api === null || api === void 0 ? void 0 : api.syncedBlock.commands.insertSyncedBlock(INPUT_METHOD.BLOCK_MENU)({
|
|
61
|
-
tr: tr
|
|
62
|
-
});
|
|
63
|
-
if (!result) {
|
|
64
|
-
return null;
|
|
65
|
-
}
|
|
66
|
-
api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.commands) === null || _api$blockControls === void 0 || _api$blockControls.toggleBlockMenu({
|
|
67
|
-
closeMenu: true
|
|
68
|
-
})({
|
|
69
|
-
tr: tr
|
|
70
|
-
});
|
|
71
|
-
api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 || _api$blockControls2.stopPreservingSelection()({
|
|
72
|
-
tr: tr
|
|
73
|
-
});
|
|
74
|
-
return tr;
|
|
42
|
+
var _api$core;
|
|
43
|
+
// Insert the synced block, close the block menu, and stop preserving the
|
|
44
|
+
// selection — all in a single transaction, mirroring the block-menu delete
|
|
45
|
+
// item. Stopping preservation is required so the caret that
|
|
46
|
+
// insertSyncedBlock places inside the new block survives; otherwise
|
|
47
|
+
// block-controls restores a whole-node NodeSelection over it, hiding the
|
|
48
|
+
// caret (EDITOR-7949). Then re-focus the editor so the caret is active,
|
|
49
|
+
// but only when the transaction was actually dispatched — otherwise a
|
|
50
|
+
// failed insertion would still steal DOM focus into the editor.
|
|
51
|
+
var dispatched = api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(function (_ref3) {
|
|
52
|
+
var _api$blockControls, _api$blockControls2;
|
|
53
|
+
var tr = _ref3.tr;
|
|
54
|
+
// If the insertion fails, bail out without closing the menu or
|
|
55
|
+
// stopping selection preservation — otherwise we would dispatch an
|
|
56
|
+
// effectively-empty transaction and close the menu despite nothing
|
|
57
|
+
// having been inserted.
|
|
58
|
+
var result = api === null || api === void 0 ? void 0 : api.syncedBlock.commands.insertSyncedBlock(INPUT_METHOD.BLOCK_MENU)({
|
|
59
|
+
tr: tr
|
|
75
60
|
});
|
|
76
|
-
if (
|
|
77
|
-
|
|
78
|
-
api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.focus();
|
|
61
|
+
if (!result) {
|
|
62
|
+
return null;
|
|
79
63
|
}
|
|
80
|
-
|
|
64
|
+
api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.commands) === null || _api$blockControls === void 0 || _api$blockControls.toggleBlockMenu({
|
|
65
|
+
closeMenu: true
|
|
66
|
+
})({
|
|
67
|
+
tr: tr
|
|
68
|
+
});
|
|
69
|
+
api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 || _api$blockControls2.stopPreservingSelection()({
|
|
70
|
+
tr: tr
|
|
71
|
+
});
|
|
72
|
+
return tr;
|
|
73
|
+
});
|
|
74
|
+
if (dispatched) {
|
|
75
|
+
var _api$core2;
|
|
76
|
+
api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.focus();
|
|
81
77
|
}
|
|
82
|
-
|
|
83
|
-
// Legacy behaviour: insert then close the block menu as two separate executes
|
|
84
|
-
// (batching them caused selection collisions — EDITOR-2751).
|
|
85
|
-
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.insertSyncedBlock(INPUT_METHOD.BLOCK_MENU));
|
|
86
|
-
api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || (_api$blockControls3 = _api$blockControls3.commands) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.toggleBlockMenu({
|
|
87
|
-
closeMenu: true
|
|
88
|
-
}));
|
|
89
78
|
};
|
|
90
79
|
var isOffline = isOfflineMode(mode);
|
|
91
80
|
var lozenge = /*#__PURE__*/React.createElement(SyncedBlockNewLozenge, {
|
|
@@ -114,9 +103,9 @@ var CopySyncedBlockDropdownItem = function CopySyncedBlockDropdownItem(_ref4) {
|
|
|
114
103
|
}),
|
|
115
104
|
mode = _useSharedPluginState2.mode;
|
|
116
105
|
var onClick = function onClick() {
|
|
117
|
-
var _api$
|
|
118
|
-
api === null || api === void 0 || (_api$
|
|
119
|
-
api === null || api === void 0 || (_api$
|
|
106
|
+
var _api$core3, _api$core4, _api$blockControls3;
|
|
107
|
+
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(INPUT_METHOD.BLOCK_MENU));
|
|
108
|
+
api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || (_api$blockControls3 = _api$blockControls3.commands) === null || _api$blockControls3 === void 0 ? void 0 : _api$blockControls3.toggleBlockMenu({
|
|
120
109
|
closeMenu: true
|
|
121
110
|
}));
|
|
122
111
|
};
|