@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.
Files changed (39) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/cjs/editor-commands/index.js +8 -18
  3. package/dist/cjs/nodeviews/bodiedSyncedBlock.js +3 -7
  4. package/dist/cjs/nodeviews/syncedBlock.js +9 -15
  5. package/dist/cjs/pm-plugins/main.js +14 -42
  6. package/dist/cjs/pm-plugins/utils/handle-bodied-sync-block-removal.js +36 -54
  7. package/dist/cjs/syncedBlockPlugin.js +1 -4
  8. package/dist/cjs/ui/CreateSyncedBlockButton.js +23 -35
  9. package/dist/cjs/ui/CreateSyncedBlockDropdownItem.js +36 -47
  10. package/dist/cjs/ui/SyncBlockLabel.js +2 -13
  11. package/dist/cjs/ui/SyncBlockRendererWrapper.js +7 -9
  12. package/dist/cjs/ui/SyncedLocationDropdown.js +53 -116
  13. package/dist/cjs/ui/floating-toolbar.js +1 -2
  14. package/dist/es2019/editor-commands/index.js +8 -18
  15. package/dist/es2019/nodeviews/bodiedSyncedBlock.js +3 -7
  16. package/dist/es2019/nodeviews/syncedBlock.js +9 -15
  17. package/dist/es2019/pm-plugins/main.js +16 -41
  18. package/dist/es2019/pm-plugins/utils/handle-bodied-sync-block-removal.js +33 -51
  19. package/dist/es2019/syncedBlockPlugin.js +1 -4
  20. package/dist/es2019/ui/CreateSyncedBlockButton.js +25 -36
  21. package/dist/es2019/ui/CreateSyncedBlockDropdownItem.js +36 -47
  22. package/dist/es2019/ui/SyncBlockLabel.js +2 -13
  23. package/dist/es2019/ui/SyncBlockRendererWrapper.js +7 -9
  24. package/dist/es2019/ui/SyncedLocationDropdown.js +1 -58
  25. package/dist/es2019/ui/floating-toolbar.js +1 -2
  26. package/dist/esm/editor-commands/index.js +8 -18
  27. package/dist/esm/nodeviews/bodiedSyncedBlock.js +3 -7
  28. package/dist/esm/nodeviews/syncedBlock.js +9 -15
  29. package/dist/esm/pm-plugins/main.js +15 -43
  30. package/dist/esm/pm-plugins/utils/handle-bodied-sync-block-removal.js +36 -54
  31. package/dist/esm/syncedBlockPlugin.js +1 -4
  32. package/dist/esm/ui/CreateSyncedBlockButton.js +23 -35
  33. package/dist/esm/ui/CreateSyncedBlockDropdownItem.js +36 -47
  34. package/dist/esm/ui/SyncBlockLabel.js +2 -13
  35. package/dist/esm/ui/SyncBlockRendererWrapper.js +7 -9
  36. package/dist/esm/ui/SyncedLocationDropdown.js +53 -116
  37. package/dist/esm/ui/floating-toolbar.js +1 -2
  38. package/dist/types/pm-plugins/main.d.ts +2 -4
  39. 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 && fg('platform_synced_block_patch_13')) {
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
- if (fg('platform_editor_blocks_patch_4')) {
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
- if (fg('platform_editor_blocks_patch_4')) {
145
- // Place the caret on the first editable position inside the converted
146
- // content so typing continues inside the synced block (EDITOR-7949).
147
- tr = placeCaretInsideBodiedSyncBlock(tr, _newBodiedSyncBlockNode.attrs.localId);
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 && fg('platform_editor_blocks_patch_4') && {
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). Gated so the
337
- // gate-off transaction is unchanged.
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 if (fg('platform_synced_block_patch_14')) {
48
- // Render the label into a separate container for the patch path so
49
- // portal implementations that write directly into the target do not clobber
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
- if (fg('platform_synced_block_patch_14')) {
66
- // Prevent native browser drag on the contentEditable="false" wrapper.
67
- // Without this, clicking in empty space (outside the contentEditable
68
- // renderer but inside the domRef) initiates a native element drag.
69
- domRef.draggable = false;
70
- this.dragStartHandler = function (e) {
71
- e.preventDefault();
72
- };
73
- // eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop, @repo/internal/dom-events/no-unsafe-event-listeners
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, rebaseTransaction } from '@atlaskit/editor-synced-block-provider';
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. Only read behind
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. Consumed behind
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
- if (!fg('platform_editor_blocks_patch_4')) {
312
- // Legacy stash-and-rebase path: store the original delete transaction so it
313
- // can be rebased against intervening edits and replayed on confirm. When
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 && fg('platform_synced_block_patch_13')) {
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
- // When fg is ON, this replaces the constructor call in the nodeview
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
- if (fg('platform_synced_block_patch_13') || Boolean(options === null || options === void 0 ? void 0 : options.onGiveFeedback) && expValEqualsNoExposure('platform_editor_sync_block_activation', 'isEnabled', true)) {
927
- ctx.consumeCutEvent();
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 = isSyncedBlockPatch13Enabled && wasCut;
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 (isSyncedBlockPatch13Enabled && isCut) {
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
- // Legacy stash-and-rebase path. When platform_editor_blocks_patch_4 is on the
1161
- // delete is recomputed fresh from the live document on confirm, so there is
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$core3;
42
- if (fg('platform_editor_blocks_patch_4')) {
43
- var _api$core2;
44
- // Recompute the delete fresh from the live document instead of
45
- // replaying a stashed-and-rebased transaction. The stash/rebase
46
- // approach produced stale, schema-invalid transactions when the
47
- // document changed shape (local edits or remote collab) while the
48
- // confirmation modal was open — the dominant signature being
49
- // "Invalid content for node bodiedSyncBlock: <>". See EDITOR-7889.
50
- api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.execute(function (_ref2) {
51
- var tr = _ref2.tr;
52
- // EDITOR-8230: unsync must remove only the sync wrapper and keep the block's
53
- // content inline, whereas delete removes the whole block. Before this branch,
54
- // the confirm path always recomputed a full delete, so unsyncing a source block
55
- // silently deleted its content. When the deletion was actually triggered by
56
- // unsync, recompute an unwrap (replaceWith content) instead of a delete.
57
- var isUnsync = fg('platform_editor_blocks_patch_6') && deletionReason === 'source-block-unsynced';
58
- var recomputedTr = isUnsync ? recomputeUnsyncTransaction(tr, syncBlockStore.sourceManager.isSourceBlock, bodiedSyncBlockRemoved.map(function (node) {
59
- return node.attrs;
60
- })) : recomputeDeleteTransaction(tr, syncBlockStore.sourceManager.isSourceBlock, bodiedSyncBlockRemoved.map(function (node) {
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
- // The target node(s) no longer exist in the live document (e.g.
65
- // a remote collaborator already removed them). There is nothing
66
- // to delete locally, so return `null` to skip the dispatch
67
- // entirely — dispatching the untouched transaction would be a
68
- // no-op that still runs the plugin's filter/append hooks. The
69
- // backend deletion has already been issued by the store manager.
70
- if (!recomputedTr) {
71
- return null;
72
- }
73
- recomputedTr.setMeta('isConfirmedSyncBlockDeletion', true);
74
- feedbackCallbacks === null || feedbackCallbacks === void 0 || feedbackCallbacks.onDeleteTransaction(recomputedTr);
75
- if (!recomputedTr.getMeta(pmHistoryPluginKey)) {
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
- trToDispatch.setMeta('addToHistory', false);
76
+ recomputedTr.setMeta('addToHistory', false);
95
77
  }
96
- return trToDispatch;
78
+ return recomputedTr;
97
79
  });
98
80
  }, function (success) {
99
- var _api$core4;
81
+ var _api$core3;
100
82
  feedbackCallbacks === null || feedbackCallbacks === void 0 || feedbackCallbacks.onDeleteCompleted(success);
101
- api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(function (_ref3) {
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
- if (fg('platform_synced_block_patch_14')) {
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$core3, _api$core4;
32
- if (fg('platform_editor_blocks_patch_4')) {
33
- var _api$core;
34
- // Insert the synced block and stop preserving the selection in a single
35
- // transaction so the caret that insertSyncedBlock places inside the new
36
- // block survives (EDITOR-7949). The toolbar is not normally opened via the
37
- // block menu, but stopping preservation is defensive and keeps behaviour
38
- // consistent with the block-menu create item should preservation ever be
39
- // active (e.g. a block is selected via block-controls). Then re-focus so
40
- // the caret is active, but only when the transaction was actually
41
- // dispatched — otherwise a failed insertion would still steal DOM focus
42
- // into the editor (mirrors CreateSyncedBlockDropdownItem).
43
- var dispatched = api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(function (_ref2) {
44
- var _api$blockControls;
45
- var tr = _ref2.tr;
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 (dispatched) {
58
- var _api$core2;
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
- return;
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
- api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.focus();
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$core3, _api$core4, _api$blockControls3;
43
- if (fg('platform_editor_blocks_patch_4')) {
44
- var _api$core;
45
- // Insert the synced block, close the block menu, and stop preserving the
46
- // selection — all in a single transaction, mirroring the block-menu delete
47
- // item. Stopping preservation is required so the caret that
48
- // insertSyncedBlock places inside the new block survives; otherwise
49
- // block-controls restores a whole-node NodeSelection over it, hiding the
50
- // caret (EDITOR-7949). Then re-focus the editor so the caret is active,
51
- // but only when the transaction was actually dispatched — otherwise a
52
- // failed insertion would still steal DOM focus into the editor.
53
- var dispatched = api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(function (_ref3) {
54
- var _api$blockControls, _api$blockControls2;
55
- var tr = _ref3.tr;
56
- // If the insertion fails, bail out without closing the menu or
57
- // stopping selection preservation — otherwise we would dispatch an
58
- // effectively-empty transaction and close the menu despite nothing
59
- // having been inserted.
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 (dispatched) {
77
- var _api$core2;
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
- return;
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$core5, _api$core6, _api$blockControls4;
118
- api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 || _api$core5.actions.execute(api === null || api === void 0 ? void 0 : api.syncedBlock.commands.copySyncedBlockReferenceToClipboard(INPUT_METHOD.BLOCK_MENU));
119
- api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || (_api$blockControls4 = _api$blockControls4.commands) === null || _api$blockControls4 === void 0 ? void 0 : _api$blockControls4.toggleBlockMenu({
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
  };