@atlaskit/editor-plugin-synced-block 12.0.4 → 12.0.6

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 +4 -13
@@ -9,9 +9,8 @@ import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity';
9
9
  import { NodeSelection, PluginKey } from '@atlaskit/editor-prosemirror/state';
10
10
  import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
11
11
  import { DecorationSet, Decoration } from '@atlaskit/editor-prosemirror/view';
12
- import { convertPMNodesToSyncBlockNodes, rebaseTransaction } from '@atlaskit/editor-synced-block-provider';
12
+ import { convertPMNodesToSyncBlockNodes } from '@atlaskit/editor-synced-block-provider';
13
13
  import { getSourceProductFromResourceIdSafe } from '@atlaskit/editor-synced-block-provider/utils';
14
- import { fg } from '@atlaskit/platform-feature-flags';
15
14
  import { expValEqualsNoExposure } from '@atlaskit/tmp-editor-statsig/exp-val-equals-no-exposure';
16
15
  import { bodiedSyncBlockNodeView } from '../nodeviews/bodiedSyncedBlock';
17
16
  import { SyncBlock as SyncBlockView } from '../nodeviews/syncedBlock';
@@ -32,8 +31,7 @@ export const syncedBlockPluginKey = new PluginKey('syncedBlockPlugin');
32
31
  * `deleteButton` (otherwise indistinguishable from a keyboard delete — both are
33
32
  * plain ReplaceSteps). A separate key (rather than `syncedBlockPluginKey`, which
34
33
  * carries plugin-state transitions read in `apply()`, or a bare string) keeps
35
- * this transient signal uniquely namespaced and isolated. Only read behind
36
- * `platform_editor_blocks_patch_4`.
34
+ * this transient signal uniquely namespaced and isolated.
37
35
  */
38
36
  export const deleteMechanismMetaKey = new PluginKey('syncedBlockDeleteMechanism');
39
37
  const syncedBlockPromptedFeedbackMetaKey = new PluginKey('syncedBlockPromptedFeedback');
@@ -42,8 +40,7 @@ const syncedBlockPromptedFeedbackMetaKey = new PluginKey('syncedBlockPromptedFee
42
40
  * Creation-type signals set by {@link createSyncedBlock} on the creating
43
41
  * transaction. The async creation handler forwards them to the store manager,
44
42
  * which attaches them to the `syncedBlockCreate` event. A dedicated key keeps
45
- * this transient signal isolated from plugin state. Consumed behind
46
- * `platform_editor_blocks_patch_4`.
43
+ * this transient signal isolated from plugin state.
47
44
  */
48
45
 
49
46
  export const creationMetaKey = new PluginKey('syncedBlockCreationMeta');
@@ -288,17 +285,9 @@ const filterTransactionOnline = ({
288
285
  });
289
286
  });
290
287
  if (bodiedSyncBlockRemoved.length > 0) {
291
- if (!fg('platform_editor_blocks_patch_4')) {
292
- // Legacy stash-and-rebase path: store the original delete transaction so it
293
- // can be rebased against intervening edits and replayed on confirm. When
294
- // platform_editor_blocks_patch_4 is on we instead recompute the delete fresh
295
- // from the live document on confirm (see handleBodiedSyncBlockRemoval), so
296
- // there is no need to stash the transaction here. See EDITOR-7889.
297
- // eslint-disable-next-line no-param-reassign
298
- confirmationTransactionRef.current = tr;
299
- }
300
- // Only derive the mechanism behind the gate — discarded gate-off.
301
- const mechanism = fg('platform_editor_blocks_patch_4') ? getDeleteMechanism(tr, state) : undefined;
288
+ // Recompute the delete fresh from the live document on confirm
289
+ // (see handleBodiedSyncBlockRemoval). See EDITOR-7889.
290
+ const mechanism = getDeleteMechanism(tr, state);
302
291
  const feedbackContext = entryPoint && getDeleteReason(tr) !== 'source-block-unsynced' ? {
303
292
  blockType: 'source',
304
293
  entryPoint
@@ -330,7 +319,7 @@ const filterTransactionOnline = ({
330
319
  // be wrong. The bodiedSyncBlock content will still be inserted but will
331
320
  // not be registered as a source block in Block Service, which is safer
332
321
  // than creating a zombie block under the wrong ARI.
333
- if (isPasteOrDrop && fg('platform_synced_block_patch_13')) {
322
+ if (isPasteOrDrop) {
334
323
  return true;
335
324
  }
336
325
 
@@ -635,8 +624,8 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
635
624
  const syncBlockNodes = instance.doc.children.filter(syncBlockStore.referenceManager.isReferenceBlock);
636
625
  syncBlockStore.referenceManager.fetchSyncBlocksData(convertPMNodesToSyncBlockNodes(syncBlockNodes));
637
626
 
638
- // Populate source sync block cache from initial document
639
- // When fg is ON, this replaces the constructor call in the nodeview
627
+ // Populate source sync block cache from initial document.
628
+ // This replaces the constructor call in the nodeview.
640
629
  instance.doc.forEach(node => {
641
630
  if (syncBlockStore.sourceManager.isSourceBlock(node)) {
642
631
  syncBlockStore.sourceManager.updateSyncBlockData(node, false);
@@ -867,18 +856,12 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
867
856
  return false;
868
857
  },
869
858
  cut: () => {
870
- 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)) {
871
- ctx.consumeCutEvent();
872
- ctx.markCutEvent();
873
- }
859
+ ctx.consumeCutEvent();
860
+ ctx.markCutEvent();
874
861
  return false;
875
862
  }
876
863
  },
877
864
  transformPasted: (slice, _view) => {
878
- if (!fg('platform_synced_block_patch_13')) {
879
- return slice;
880
- }
881
-
882
865
  // Defense against bodiedSyncBlock nodes arriving via paste
883
866
  // (e.g. drag-and-drop, cut-paste, or browser-level clipboard
884
867
  // operations that bypass the transformCopied handler).
@@ -907,9 +890,8 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
907
890
  schema
908
891
  } = state;
909
892
  const isCopy = ctx.consumeCopyEvent();
910
- const isSyncedBlockPatch13Enabled = fg('platform_synced_block_patch_13');
911
893
  const wasCut = ctx.consumeCutEvent();
912
- const isCut = isSyncedBlockPatch13Enabled && wasCut;
894
+ const isCut = wasCut;
913
895
  const isPromptedFeedbackCut = Boolean(syncBlockStore && (options === null || options === void 0 ? void 0 : options.onGiveFeedback) && wasCut) && expValEqualsNoExposure('platform_editor_sync_block_activation', 'isEnabled', true);
914
896
  if (!syncBlockStore || !isCopy && !isCut && !isPromptedFeedbackCut) {
915
897
  return slice;
@@ -947,7 +929,7 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
947
929
  if (!sliceFullyContainsNode(slice, node)) {
948
930
  return node.content;
949
931
  }
950
- if (isSyncedBlockPatch13Enabled && isCut) {
932
+ if (isCut) {
951
933
  return node;
952
934
  }
953
935
  const newResourceId = syncBlockStore.referenceManager.generateResourceIdForReference(node.attrs.resourceId);
@@ -1094,16 +1076,9 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
1094
1076
  });
1095
1077
  }
1096
1078
 
1097
- // Legacy stash-and-rebase path. When platform_editor_blocks_patch_4 is on the
1098
- // delete is recomputed fresh from the live document on confirm, so there is
1099
- // no stashed transaction to rebase here. See EDITOR-7889.
1100
- if (!fg('platform_editor_blocks_patch_4')) {
1101
- trs.filter(tr => tr.docChanged).forEach(tr => {
1102
- if (confirmationTransactionRef.current) {
1103
- confirmationTransactionRef.current = rebaseTransaction(confirmationTransactionRef.current, tr, newState);
1104
- }
1105
- });
1106
- }
1079
+ // Delete is recomputed fresh from the live document on confirm.
1080
+ // See EDITOR-7889.
1081
+
1107
1082
  for (const tr of trs) {
1108
1083
  if (tr.getMeta(pmHistoryPluginKey)) {
1109
1084
  const {
@@ -30,64 +30,46 @@ export const handleBodiedSyncBlockRemoval = (bodiedSyncBlockRemoved, syncBlockSt
30
30
  // See editor-common/src/sync-block/sync-block-store-manager.ts for how we handle user confirmation and
31
31
  // proceed with deletion.
32
32
  syncBlockStore.sourceManager.deleteSyncBlocksWithConfirmation(bodiedSyncBlockRemoved.map(node => node.attrs), deletionReason, () => {
33
- var _api$core3;
34
- if (fg('platform_editor_blocks_patch_4')) {
35
- var _api$core2;
36
- // Recompute the delete fresh from the live document instead of
37
- // replaying a stashed-and-rebased transaction. The stash/rebase
38
- // approach produced stale, schema-invalid transactions when the
39
- // document changed shape (local edits or remote collab) while the
40
- // confirmation modal was open — the dominant signature being
41
- // "Invalid content for node bodiedSyncBlock: <>". See EDITOR-7889.
42
- api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute(({
43
- tr
44
- }) => {
45
- // EDITOR-8230: unsync must remove only the sync wrapper and keep the block's
46
- // content inline, whereas delete removes the whole block. Before this branch,
47
- // the confirm path always recomputed a full delete, so unsyncing a source block
48
- // silently deleted its content. When the deletion was actually triggered by
49
- // unsync, recompute an unwrap (replaceWith content) instead of a delete.
50
- const isUnsync = fg('platform_editor_blocks_patch_6') && deletionReason === 'source-block-unsynced';
51
- const recomputedTr = isUnsync ? recomputeUnsyncTransaction(tr, syncBlockStore.sourceManager.isSourceBlock, bodiedSyncBlockRemoved.map(node => node.attrs)) : recomputeDeleteTransaction(tr, syncBlockStore.sourceManager.isSourceBlock, bodiedSyncBlockRemoved.map(node => node.attrs));
33
+ var _api$core2;
34
+ // Recompute the delete fresh from the live document instead of
35
+ // replaying a stashed-and-rebased transaction. The stash/rebase
36
+ // approach produced stale, schema-invalid transactions when the
37
+ // document changed shape (local edits or remote collab) while the
38
+ // confirmation modal was open — the dominant signature being
39
+ // "Invalid content for node bodiedSyncBlock: <>". See EDITOR-7889.
40
+ api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.execute(({
41
+ tr
42
+ }) => {
43
+ // EDITOR-8230: unsync must remove only the sync wrapper and keep the block's
44
+ // content inline, whereas delete removes the whole block. Before this branch,
45
+ // the confirm path always recomputed a full delete, so unsyncing a source block
46
+ // silently deleted its content. When the deletion was actually triggered by
47
+ // unsync, recompute an unwrap (replaceWith content) instead of a delete.
48
+ const isUnsync = fg('platform_editor_blocks_patch_6') && deletionReason === 'source-block-unsynced';
49
+ const recomputedTr = isUnsync ? recomputeUnsyncTransaction(tr, syncBlockStore.sourceManager.isSourceBlock, bodiedSyncBlockRemoved.map(node => node.attrs)) : recomputeDeleteTransaction(tr, syncBlockStore.sourceManager.isSourceBlock, bodiedSyncBlockRemoved.map(node => node.attrs));
52
50
 
53
- // The target node(s) no longer exist in the live document (e.g.
54
- // a remote collaborator already removed them). There is nothing
55
- // to delete locally, so return `null` to skip the dispatch
56
- // entirely — dispatching the untouched transaction would be a
57
- // no-op that still runs the plugin's filter/append hooks. The
58
- // backend deletion has already been issued by the store manager.
59
- if (!recomputedTr) {
60
- return null;
61
- }
62
- recomputedTr.setMeta('isConfirmedSyncBlockDeletion', true);
63
- feedbackCallbacks === null || feedbackCallbacks === void 0 ? void 0 : feedbackCallbacks.onDeleteTransaction(recomputedTr);
64
- if (!recomputedTr.getMeta(pmHistoryPluginKey)) {
65
- // bodiedSyncBlock deletion is expected to be permanent (cannot undo)
66
- // For a normal deletion (not triggered by undo), remove it from history so that it cannot be undone
67
- recomputedTr.setMeta('addToHistory', false);
68
- }
69
- return recomputedTr;
70
- });
71
- return;
72
- }
73
- const confirmationTransaction = confirmationTransactionRef.current;
74
- if (!confirmationTransaction) {
75
- return;
76
- }
77
- api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(() => {
78
- const trToDispatch = confirmationTransaction.setMeta('isConfirmedSyncBlockDeletion', true);
79
- feedbackCallbacks === null || feedbackCallbacks === void 0 ? void 0 : feedbackCallbacks.onDeleteTransaction(trToDispatch);
80
- if (!trToDispatch.getMeta(pmHistoryPluginKey)) {
51
+ // The target node(s) no longer exist in the live document (e.g.
52
+ // a remote collaborator already removed them). There is nothing
53
+ // to delete locally, so return `null` to skip the dispatch
54
+ // entirely — dispatching the untouched transaction would be a
55
+ // no-op that still runs the plugin's filter/append hooks. The
56
+ // backend deletion has already been issued by the store manager.
57
+ if (!recomputedTr) {
58
+ return null;
59
+ }
60
+ recomputedTr.setMeta('isConfirmedSyncBlockDeletion', true);
61
+ feedbackCallbacks === null || feedbackCallbacks === void 0 ? void 0 : feedbackCallbacks.onDeleteTransaction(recomputedTr);
62
+ if (!recomputedTr.getMeta(pmHistoryPluginKey)) {
81
63
  // bodiedSyncBlock deletion is expected to be permanent (cannot undo)
82
64
  // For a normal deletion (not triggered by undo), remove it from history so that it cannot be undone
83
- trToDispatch.setMeta('addToHistory', false);
65
+ recomputedTr.setMeta('addToHistory', false);
84
66
  }
85
- return trToDispatch;
67
+ return recomputedTr;
86
68
  });
87
69
  }, success => {
88
- var _api$core4;
70
+ var _api$core3;
89
71
  feedbackCallbacks === null || feedbackCallbacks === void 0 ? void 0 : feedbackCallbacks.onDeleteCompleted(success);
90
- api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.execute(({
72
+ api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(({
91
73
  tr
92
74
  }) => {
93
75
  let newState;
@@ -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, flushSyncBlocks, discardUnpublishedSyncBlocks } from './editor-actions';
8
7
  import { copySyncedBlockReferenceToClipboardEditorCommand, createSyncedBlock } from './editor-commands';
@@ -187,9 +186,7 @@ export const syncedBlockPlugin = ({
187
186
  // Destroy the SyncBlockStoreManager on editor unmount to cancel
188
187
  // pending timers, subscriptions, and in-flight fetches.
189
188
  destroy() {
190
- if (fg('platform_synced_block_patch_14')) {
191
- syncBlockStore.destroy();
192
- }
189
+ syncBlockStore.destroy();
193
190
  }
194
191
  };
195
192
  };
@@ -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 const CreateSyncedBlockButton = ({
@@ -30,45 +29,35 @@ export const CreateSyncedBlockButton = ({
30
29
  const canInsertEmptyBlock = Boolean(selection === null || selection === void 0 ? void 0 : selection.empty);
31
30
  const isDisabled = Boolean(isOfflineMode(mode) || !canBeConverted && !canInsertEmptyBlock);
32
31
  const onClick = useCallback(() => {
33
- var _api$core3, _api$core4;
34
- if (fg('platform_editor_blocks_patch_4')) {
35
- var _api$core;
36
- // Insert the synced block and stop preserving the selection in a single
37
- // transaction so the caret that insertSyncedBlock places inside the new
38
- // block survives (EDITOR-7949). The toolbar is not normally opened via the
39
- // block menu, but stopping preservation is defensive and keeps behaviour
40
- // consistent with the block-menu create item should preservation ever be
41
- // active (e.g. a block is selected via block-controls). Then re-focus so
42
- // the caret is active, but only when the transaction was actually
43
- // dispatched — otherwise a failed insertion would still steal DOM focus
44
- // into the editor (mirrors CreateSyncedBlockDropdownItem).
45
- const dispatched = api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
32
+ var _api$core;
33
+ // Insert the synced block and stop preserving the selection in a single
34
+ // transaction so the caret that insertSyncedBlock places inside the new
35
+ // block survives (EDITOR-7949). The toolbar is not normally opened via the
36
+ // block menu, but stopping preservation is defensive and keeps behaviour
37
+ // consistent with the block-menu create item should preservation ever be
38
+ // active (e.g. a block is selected via block-controls). Then re-focus so
39
+ // the caret is active, but only when the transaction was actually
40
+ // dispatched — otherwise a failed insertion would still steal DOM focus
41
+ // into the editor (mirrors CreateSyncedBlockDropdownItem).
42
+ const dispatched = api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
43
+ tr
44
+ }) => {
45
+ var _api$blockControls, _api$blockControls$co;
46
+ const result = api === null || api === void 0 ? void 0 : api.syncedBlock.commands.insertSyncedBlock(INPUT_METHOD.SYNCED_BLOCK_TB)({
46
47
  tr
47
- }) => {
48
- var _api$blockControls, _api$blockControls$co;
49
- const result = api === null || api === void 0 ? void 0 : api.syncedBlock.commands.insertSyncedBlock(INPUT_METHOD.SYNCED_BLOCK_TB)({
50
- tr
51
- });
52
- if (!result) {
53
- return null;
54
- }
55
- api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : (_api$blockControls$co = _api$blockControls.commands) === null || _api$blockControls$co === void 0 ? void 0 : _api$blockControls$co.stopPreservingSelection()({
56
- tr
57
- });
58
- return tr;
59
48
  });
60
- if (dispatched) {
61
- var _api$core2;
62
- api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.focus();
49
+ if (!result) {
50
+ return null;
63
51
  }
64
- return;
52
+ api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : (_api$blockControls$co = _api$blockControls.commands) === null || _api$blockControls$co === void 0 ? void 0 : _api$blockControls$co.stopPreservingSelection()({
53
+ tr
54
+ });
55
+ return tr;
56
+ });
57
+ if (dispatched) {
58
+ var _api$core2;
59
+ api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.focus();
65
60
  }
66
- api === null || api === void 0 ? void 0 : (_api$core3 = api.core) === null || _api$core3 === void 0 ? void 0 : _api$core3.actions.execute(({
67
- tr
68
- }) => api === null || api === void 0 ? void 0 : api.syncedBlock.commands.insertSyncedBlock(INPUT_METHOD.SYNCED_BLOCK_TB)({
69
- tr
70
- }));
71
- api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.focus();
72
61
  }, [api]);
73
62
  const message = intl.formatMessage(syncBlockMessages.syncBlockLabel);
74
63
  return /*#__PURE__*/React.createElement(ToolbarTooltip, {
@@ -39,54 +39,43 @@ const CreateSyncedBlockDropdownItem = ({
39
39
  return null;
40
40
  }
41
41
  const onClick = () => {
42
- var _api$core3, _api$core4, _api$blockControls3, _api$blockControls3$c;
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
- const dispatched = api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
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
+ const dispatched = api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
52
+ tr
53
+ }) => {
54
+ var _api$blockControls, _api$blockControls$co, _api$blockControls2, _api$blockControls2$c;
55
+ // If the insertion fails, bail out without closing the menu or
56
+ // stopping selection preservation — otherwise we would dispatch an
57
+ // effectively-empty transaction and close the menu despite nothing
58
+ // having been inserted.
59
+ const result = api === null || api === void 0 ? void 0 : api.syncedBlock.commands.insertSyncedBlock(INPUT_METHOD.BLOCK_MENU)({
54
60
  tr
55
- }) => {
56
- var _api$blockControls, _api$blockControls$co, _api$blockControls2, _api$blockControls2$c;
57
- // If the insertion fails, bail out without closing the menu or
58
- // stopping selection preservation — otherwise we would dispatch an
59
- // effectively-empty transaction and close the menu despite nothing
60
- // having been inserted.
61
- const result = api === null || api === void 0 ? void 0 : api.syncedBlock.commands.insertSyncedBlock(INPUT_METHOD.BLOCK_MENU)({
62
- tr
63
- });
64
- if (!result) {
65
- return null;
66
- }
67
- api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : (_api$blockControls$co = _api$blockControls.commands) === null || _api$blockControls$co === void 0 ? void 0 : _api$blockControls$co.toggleBlockMenu({
68
- closeMenu: true
69
- })({
70
- tr
71
- });
72
- 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.stopPreservingSelection()({
73
- tr
74
- });
75
- return tr;
76
61
  });
77
- if (dispatched) {
78
- var _api$core2;
79
- api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.focus();
62
+ if (!result) {
63
+ return null;
80
64
  }
81
- return;
65
+ api === null || api === void 0 ? void 0 : (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : (_api$blockControls$co = _api$blockControls.commands) === null || _api$blockControls$co === void 0 ? void 0 : _api$blockControls$co.toggleBlockMenu({
66
+ closeMenu: true
67
+ })({
68
+ tr
69
+ });
70
+ 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.stopPreservingSelection()({
71
+ tr
72
+ });
73
+ return tr;
74
+ });
75
+ if (dispatched) {
76
+ var _api$core2;
77
+ api === null || api === void 0 ? void 0 : (_api$core2 = api.core) === null || _api$core2 === void 0 ? void 0 : _api$core2.actions.focus();
82
78
  }
83
-
84
- // Legacy behaviour: insert then close the block menu as two separate executes
85
- // (batching them caused selection collisions — EDITOR-2751).
86
- 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.insertSyncedBlock(INPUT_METHOD.BLOCK_MENU));
87
- 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$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : (_api$blockControls3$c = _api$blockControls3.commands) === null || _api$blockControls3$c === void 0 ? void 0 : _api$blockControls3$c.toggleBlockMenu({
88
- closeMenu: true
89
- }));
90
79
  };
91
80
  const isOffline = isOfflineMode(mode);
92
81
  const lozenge = /*#__PURE__*/React.createElement(SyncedBlockNewLozenge, {
@@ -118,9 +107,9 @@ const CopySyncedBlockDropdownItem = ({
118
107
  };
119
108
  });
120
109
  const onClick = () => {
121
- var _api$core5, _api$core6, _api$blockControls4, _api$blockControls4$c;
122
- api === null || api === void 0 ? void 0 : (_api$core5 = api.core) === null || _api$core5 === void 0 ? void 0 : _api$core5.actions.execute(api === null || api === void 0 ? void 0 : api.syncedBlock.commands.copySyncedBlockReferenceToClipboard(INPUT_METHOD.BLOCK_MENU));
123
- api === null || api === void 0 ? void 0 : (_api$core6 = api.core) === null || _api$core6 === void 0 ? void 0 : _api$core6.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 ? void 0 : (_api$blockControls4$c = _api$blockControls4.commands) === null || _api$blockControls4$c === void 0 ? void 0 : _api$blockControls4$c.toggleBlockMenu({
110
+ var _api$core3, _api$core4, _api$blockControls3, _api$blockControls3$c;
111
+ 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(INPUT_METHOD.BLOCK_MENU));
112
+ 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$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 ? void 0 : (_api$blockControls3$c = _api$blockControls3.commands) === null || _api$blockControls3$c === void 0 ? void 0 : _api$blockControls3$c.toggleBlockMenu({
124
113
  closeMenu: true
125
114
  }));
126
115
  };
@@ -3,7 +3,6 @@ import { useIntl } from 'react-intl';
3
3
  import { syncBlockMessages as messages } from '@atlaskit/editor-common/messages';
4
4
  import { SyncBlockLabelSharedCssClassName } from '@atlaskit/editor-common/sync-block';
5
5
  import BlockSyncedIcon from '@atlaskit/icon-lab/core/block-synced';
6
- import { fg } from '@atlaskit/platform-feature-flags';
7
6
  import { Text } from '@atlaskit/primitives/compiled';
8
7
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
9
8
  import Tooltip from '@atlaskit/tooltip';
@@ -32,7 +31,7 @@ const SyncBlockLabelComponent = ({
32
31
  let tooltipContent = tooltipMessage;
33
32
  if (contentUpdatedAt) {
34
33
  const elapsedTime = formatElapsedTime(contentUpdatedAt, intl);
35
- tooltipContent = fg('platform_synced_block_patch_13') ? /*#__PURE__*/React.createElement("div", null, title ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, {
34
+ tooltipContent = /*#__PURE__*/React.createElement("div", null, title ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Text, {
36
35
  size: "small",
37
36
  color: "color.text.inverse",
38
37
  weight: "bold"
@@ -49,17 +48,7 @@ const SyncBlockLabelComponent = ({
49
48
  }, formatMessage(messages.referenceSyncBlockLastEdited)), /*#__PURE__*/React.createElement(Text, {
50
49
  size: "small",
51
50
  color: "color.text.inverse"
52
- }, ' ', elapsedTime)) : /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement(Text, {
53
- size: "small",
54
- color: "color.text.inverse"
55
- }, tooltipMessage), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement("br", null), /*#__PURE__*/React.createElement(Text, {
56
- size: "small",
57
- color: "color.text.inverse",
58
- weight: "bold"
59
- }, formatMessage(messages.referenceSyncBlockLastEdited)), /*#__PURE__*/React.createElement(Text, {
60
- size: "small",
61
- color: "color.text.inverse"
62
- }, elapsedTime));
51
+ }, ' ', elapsedTime));
63
52
  }
64
53
  setTooltipContent(tooltipContent);
65
54
  }, [contentUpdatedAt, formatMessage, intl, title, tooltipMessage]);
@@ -2,7 +2,6 @@ import React, { useCallback, useEffect, useRef } from 'react';
2
2
  import { bind } from 'bind-event-listener';
3
3
  import { SyncBlockSharedCssClassName } from '@atlaskit/editor-common/sync-block';
4
4
  import { SyncBlockError, useFetchSyncBlockData, useFetchSyncBlockTitle } 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 { SyncBlockLabel } from './SyncBlockLabel';
8
7
  const SyncBlockRendererWrapperDataId = 'sync-block-plugin-renderer-wrapper';
@@ -20,7 +19,6 @@ const SyncBlockRendererWrapperComponent = ({
20
19
  const contentUpdatedAt = syncBlockFetchResult === null || syncBlockFetchResult === void 0 ? void 0 : (_syncBlockFetchResult = syncBlockFetchResult.syncBlockInstance) === null || _syncBlockFetchResult === void 0 ? void 0 : (_syncBlockFetchResult2 = _syncBlockFetchResult.data) === null || _syncBlockFetchResult2 === void 0 ? void 0 : _syncBlockFetchResult2.contentUpdatedAt;
21
20
  const isUnpublishedBlock = ((_syncBlockFetchResult3 = syncBlockFetchResult.syncBlockInstance) === null || _syncBlockFetchResult3 === void 0 ? void 0 : (_syncBlockFetchResult4 = _syncBlockFetchResult3.data) === null || _syncBlockFetchResult4 === void 0 ? void 0 : _syncBlockFetchResult4.status) === 'unpublished';
22
21
  const isUnsyncedBlock = isUnpublishedBlock || (syncBlockFetchResult === null || syncBlockFetchResult === void 0 ? void 0 : (_syncBlockFetchResult5 = syncBlockFetchResult.syncBlockInstance) === null || _syncBlockFetchResult5 === void 0 ? void 0 : (_syncBlockFetchResult6 = _syncBlockFetchResult5.error) === null || _syncBlockFetchResult6 === void 0 ? void 0 : _syncBlockFetchResult6.type) === SyncBlockError.NotFound;
23
- const isTextSelectionEnabled = fg('platform_synced_block_patch_14');
24
22
 
25
23
  // Evaluated unconditionally so the experiment exposure is tracked correctly
26
24
  // (recorded on every render, not lazily on first click).
@@ -43,7 +41,7 @@ const SyncBlockRendererWrapperComponent = ({
43
41
  const rendererRef = useRef(null);
44
42
  useEffect(() => {
45
43
  const containerEl = rendererRef.current;
46
- if (!containerEl || !isTextSelectionEnabled || !isSyncBlockActivationEnabled) {
44
+ if (!containerEl || !isSyncBlockActivationEnabled) {
47
45
  return;
48
46
  }
49
47
  const unbind = bind(containerEl, {
@@ -63,25 +61,25 @@ const SyncBlockRendererWrapperComponent = ({
63
61
  }
64
62
  });
65
63
  return unbind;
66
- }, [isTextSelectionEnabled, isSyncBlockActivationEnabled]);
64
+ }, [isSyncBlockActivationEnabled]);
67
65
  return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", {
68
66
  ref: rendererRef,
69
67
  "data-testid": SyncBlockRendererWrapperDataId
70
68
  // eslint-disable-next-line @atlaskit/ui-styling-standard/no-classname-prop
71
69
  ,
72
70
  className: SyncBlockSharedCssClassName.renderer,
73
- contentEditable: isTextSelectionEnabled || undefined,
71
+ contentEditable: true,
74
72
  suppressContentEditableWarning: true
75
73
  // Prevent the contentEditable div from being keyboard-focusable.
76
74
  // It is only used to enable text selection, not as an input target.
77
75
  // eslint-disable-next-line jsx-a11y/no-noninteractive-tabindex
78
76
  ,
79
- tabIndex: isTextSelectionEnabled ? -1 : undefined,
80
- onBeforeInput: isTextSelectionEnabled ? preventInput : undefined,
81
- onPaste: isTextSelectionEnabled ? preventInput : undefined
77
+ tabIndex: -1,
78
+ onBeforeInput: preventInput,
79
+ onPaste: preventInput
82
80
  // eslint-disable-next-line @atlaskit/design-system/no-direct-use-of-web-platform-drag-and-drop
83
81
  ,
84
- onDrop: isTextSelectionEnabled ? preventInput : undefined
82
+ onDrop: preventInput
85
83
  }, syncedBlockRenderer({
86
84
  syncBlockFetchResult,
87
85
  api
@@ -1,11 +1,10 @@
1
1
  /* SyncedLocationDropdown.tsx generated by @compiled/babel-plugin v2.0.0 */
2
- import _extends from "@babel/runtime/helpers/extends";
3
2
  import "./SyncedLocationDropdown.compiled.css";
4
3
  import * as React from 'react';
5
4
  import { ax, ix } from "@compiled/react/runtime";
6
5
  import { useCallback, useEffect, useMemo, useState } from 'react';
7
6
  import { cx } from '@compiled/react';
8
- import DropdownMenu, { DropdownItem, DropdownItemGroup } from '@atlaskit/dropdown-menu';
7
+ import { DropdownItem, DropdownItemGroup } from '@atlaskit/dropdown-menu';
9
8
  import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE } from '@atlaskit/editor-common/analytics';
10
9
  import { syncBlockMessages as messages } from '@atlaskit/editor-common/messages';
11
10
  import { SYNCED_BLOCKS_DOCUMENTATION_URL } from '@atlaskit/editor-common/sync-block';
@@ -26,7 +25,6 @@ import SubtaskIcon from '@atlaskit/icon/core/subtasks';
26
25
  import TaskIcon from '@atlaskit/icon/core/task';
27
26
  import { ConfluenceIcon, JiraIcon, AtlassianIcon } from '@atlaskit/logo';
28
27
  import Lozenge from '@atlaskit/lozenge';
29
- import { fg } from '@atlaskit/platform-feature-flags';
30
28
  import { Box, Text, Inline, Anchor, Stack } from '@atlaskit/primitives/compiled';
31
29
  import Spinner from '@atlaskit/spinner';
32
30
  import { expValEquals } from '@atlaskit/tmp-editor-statsig/exp-val-equals';
@@ -297,16 +295,6 @@ export const SyncedLocationDropdown = ({
297
295
  api,
298
296
  floatingToolbarRenderContext
299
297
  }) => {
300
- if (!fg('platform_synced_block_patch_13')) {
301
- return /*#__PURE__*/React.createElement(LegacySyncedLocationDropdown, {
302
- syncBlockStore: syncBlockStore,
303
- resourceId: resourceId,
304
- intl: intl,
305
- isSource: isSource,
306
- localId: localId,
307
- api: api
308
- });
309
- }
310
298
  return /*#__PURE__*/React.createElement(EditorPositionedSyncedLocationDropdown, {
311
299
  syncBlockStore: syncBlockStore,
312
300
  resourceId: resourceId,
@@ -381,51 +369,6 @@ const EditorPositionedSyncedLocationDropdown = ({
381
369
  }
382
370
  }, content);
383
371
  };
384
- const LegacySyncedLocationDropdown = ({
385
- syncBlockStore,
386
- resourceId,
387
- intl,
388
- isSource,
389
- localId,
390
- api
391
- }) => {
392
- const triggerTitle = intl.formatMessage(messages.syncedLocationDropdownTitle);
393
- const [isOpen, setIsOpen] = useState(false);
394
- const content = isOpen ? /*#__PURE__*/React.createElement(DropdownContent, {
395
- syncBlockStore: syncBlockStore,
396
- resourceId: resourceId,
397
- intl: intl,
398
- isSource: isSource,
399
- localId: localId,
400
- api: api
401
- }) : null;
402
- return /*#__PURE__*/React.createElement(DropdownMenu, {
403
- isOpen: isOpen
404
- // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
405
- ,
406
- onOpenChange: ({
407
- isOpen
408
- }) => setIsOpen(isOpen),
409
- testId: SYNCED_LOCATIONS_DROPDOWN_TEST_ID
410
- // eslint-disable-next-line @atlassian/perf-linting/no-unstable-inline-props -- Ignored via go/ees017 (to be fixed)
411
- ,
412
- trigger: ({
413
- triggerRef,
414
- ...triggerProps
415
- }) => /*#__PURE__*/React.createElement(Button, _extends({
416
- ref: triggerRef,
417
- areAnyNewToolbarFlagsEnabled: true,
418
- selected: isOpen,
419
- iconAfter: /*#__PURE__*/React.createElement(ChevronDownIcon, {
420
- color: "currentColor",
421
- spacing: "spacious",
422
- label: "",
423
- size: "small"
424
- })
425
- // eslint-disable-next-line react/jsx-props-no-spreading
426
- }, triggerProps), triggerTitle)
427
- }, content);
428
- };
429
372
  export const SyncedLocationDropdownWithCount = ({
430
373
  syncBlockStore,
431
374
  resourceId,