@atlaskit/editor-plugin-synced-block 5.3.11 → 5.3.13

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 (62) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/afm-cc/tsconfig.json +0 -3
  3. package/afm-jira/tsconfig.json +0 -3
  4. package/afm-products/tsconfig.json +0 -3
  5. package/dist/cjs/editor-commands/index.js +99 -40
  6. package/dist/cjs/nodeviews/bodiedSyncedBlock.js +2 -7
  7. package/dist/cjs/nodeviews/syncedBlock.js +4 -18
  8. package/dist/cjs/pm-plugins/main.js +34 -43
  9. package/dist/cjs/pm-plugins/menu-and-toolbar-experiences.js +221 -81
  10. package/dist/cjs/pm-plugins/utils/track-sync-blocks.js +1 -2
  11. package/dist/cjs/pm-plugins/utils/utils.js +1 -46
  12. package/dist/cjs/syncedBlockPlugin.js +5 -7
  13. package/dist/cjs/types/index.js +5 -1
  14. package/dist/cjs/ui/CreateSyncedBlockDropdownItem.js +2 -1
  15. package/dist/cjs/ui/DeleteConfirmationModal.js +4 -20
  16. package/dist/cjs/ui/SyncBlockLabel.js +4 -10
  17. package/dist/cjs/ui/SyncBlockRefresher.js +7 -9
  18. package/dist/cjs/ui/SyncedLocationDropdown.js +32 -6
  19. package/dist/cjs/ui/floating-toolbar.js +11 -7
  20. package/dist/es2019/editor-commands/index.js +99 -40
  21. package/dist/es2019/nodeviews/bodiedSyncedBlock.js +2 -7
  22. package/dist/es2019/nodeviews/syncedBlock.js +4 -15
  23. package/dist/es2019/pm-plugins/main.js +33 -42
  24. package/dist/es2019/pm-plugins/menu-and-toolbar-experiences.js +206 -71
  25. package/dist/es2019/pm-plugins/utils/track-sync-blocks.js +1 -2
  26. package/dist/es2019/pm-plugins/utils/utils.js +0 -47
  27. package/dist/es2019/syncedBlockPlugin.js +4 -5
  28. package/dist/es2019/types/index.js +5 -1
  29. package/dist/es2019/ui/CreateSyncedBlockDropdownItem.js +2 -1
  30. package/dist/es2019/ui/DeleteConfirmationModal.js +4 -20
  31. package/dist/es2019/ui/SyncBlockLabel.js +4 -10
  32. package/dist/es2019/ui/SyncBlockRefresher.js +7 -9
  33. package/dist/es2019/ui/SyncedLocationDropdown.js +30 -6
  34. package/dist/es2019/ui/floating-toolbar.js +10 -6
  35. package/dist/esm/editor-commands/index.js +99 -40
  36. package/dist/esm/nodeviews/bodiedSyncedBlock.js +2 -7
  37. package/dist/esm/nodeviews/syncedBlock.js +4 -18
  38. package/dist/esm/pm-plugins/main.js +34 -43
  39. package/dist/esm/pm-plugins/menu-and-toolbar-experiences.js +221 -81
  40. package/dist/esm/pm-plugins/utils/track-sync-blocks.js +1 -2
  41. package/dist/esm/pm-plugins/utils/utils.js +0 -45
  42. package/dist/esm/syncedBlockPlugin.js +5 -7
  43. package/dist/esm/types/index.js +5 -1
  44. package/dist/esm/ui/CreateSyncedBlockDropdownItem.js +2 -1
  45. package/dist/esm/ui/DeleteConfirmationModal.js +4 -20
  46. package/dist/esm/ui/SyncBlockLabel.js +4 -10
  47. package/dist/esm/ui/SyncBlockRefresher.js +7 -9
  48. package/dist/esm/ui/SyncedLocationDropdown.js +32 -6
  49. package/dist/esm/ui/floating-toolbar.js +11 -7
  50. package/dist/types/editor-commands/index.d.ts +3 -2
  51. package/dist/types/pm-plugins/utils/handle-bodied-sync-block-removal.d.ts +1 -1
  52. package/dist/types/pm-plugins/utils/utils.d.ts +1 -3
  53. package/dist/types/syncedBlockPluginType.d.ts +2 -1
  54. package/dist/types/types/index.d.ts +4 -0
  55. package/dist/types/ui/SyncedLocationDropdown.d.ts +4 -1
  56. package/dist/types-ts4.5/editor-commands/index.d.ts +3 -2
  57. package/dist/types-ts4.5/pm-plugins/utils/handle-bodied-sync-block-removal.d.ts +1 -1
  58. package/dist/types-ts4.5/pm-plugins/utils/utils.d.ts +1 -3
  59. package/dist/types-ts4.5/syncedBlockPluginType.d.ts +2 -1
  60. package/dist/types-ts4.5/types/index.d.ts +4 -0
  61. package/dist/types-ts4.5/ui/SyncedLocationDropdown.d.ts +4 -1
  62. package/package.json +5 -6
@@ -7,9 +7,7 @@ import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity';
7
7
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
8
8
  import { DecorationSet, Decoration } from '@atlaskit/editor-prosemirror/view';
9
9
  import { convertPMNodesToSyncBlockNodes, rebaseTransaction } from '@atlaskit/editor-synced-block-provider';
10
- import { fg } from '@atlaskit/platform-feature-flags';
11
10
  import { lazyBodiedSyncBlockView } from '../nodeviews/bodiedLazySyncedBlock';
12
- import { lazySyncBlockView } from '../nodeviews/lazySyncedBlock';
13
11
  import { SyncBlock as SyncBlockView } from '../nodeviews/syncedBlock';
14
12
  import { FLAG_ID } from '../types';
15
13
  import { handleBodiedSyncBlockRemoval } from './utils/handle-bodied-sync-block-removal';
@@ -52,7 +50,7 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
52
50
  const unpublishedFlagShown = new Set();
53
51
 
54
52
  // Set up callback to detect unpublished sync blocks when they're fetched
55
- fg('platform_synced_block_dogfooding') && syncBlockStore.referenceManager.setOnUnpublishedSyncBlockDetected(resourceId => {
53
+ syncBlockStore.referenceManager.setOnUnpublishedSyncBlockDetected(resourceId => {
56
54
  // Only show the flag once per sync block
57
55
  if (!unpublishedFlagShown.has(resourceId)) {
58
56
  unpublishedFlagShown.add(resourceId);
@@ -104,7 +102,7 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
104
102
  },
105
103
  props: {
106
104
  nodeViews: {
107
- syncBlock: fg('platform_synced_block_dogfooding') ? (node, view, getPos, _decorations) => {
105
+ syncBlock: (node, view, getPos, _decorations) => {
108
106
  // To support SSR, pass `syncBlockStore` here
109
107
  // and do not use lazy loading.
110
108
  // We cannot start rendering and then load `syncBlockStore` asynchronously,
@@ -119,11 +117,7 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
119
117
  eventDispatcher: pmPluginFactoryParams.eventDispatcher,
120
118
  syncBlockStore: syncBlockStore
121
119
  }).init();
122
- } : lazySyncBlockView({
123
- options,
124
- pmPluginFactoryParams,
125
- api
126
- }),
120
+ },
127
121
  bodiedSyncBlock: lazyBodiedSyncBlockView({
128
122
  pluginOptions: options,
129
123
  pmPluginFactoryParams,
@@ -217,7 +211,7 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
217
211
  const isConfirmedSyncBlockDeletion = Boolean(tr.getMeta('isConfirmedSyncBlockDeletion'));
218
212
 
219
213
  // Track newly added reference sync blocks before processing the transaction
220
- if (tr.docChanged && !tr.getMeta('isRemote') && fg('platform_synced_block_dogfooding')) {
214
+ if (tr.docChanged && !tr.getMeta('isRemote')) {
221
215
  const {
222
216
  added
223
217
  } = trackSyncBlocks(node => node.type.name === 'syncBlock', tr, state);
@@ -242,42 +236,39 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
242
236
  added: bodiedSyncBlockAdded
243
237
  } = trackSyncBlocks(syncBlockStore.sourceManager.isSourceBlock, tr, state);
244
238
  if (!isOffline) {
245
- if (fg('platform_synced_block_dogfooding')) {
246
- const {
247
- removed: syncBlockRemoved,
248
- added: syncBlockAdded
249
- } = trackSyncBlocks(node => node.type.name === 'syncBlock', tr, state);
250
- syncBlockRemoved.forEach(syncBlock => {
251
- var _api$analytics, _api$analytics$action;
252
- api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : (_api$analytics$action = _api$analytics.actions) === null || _api$analytics$action === void 0 ? void 0 : _api$analytics$action.fireAnalyticsEvent({
253
- action: ACTION.DELETED,
254
- actionSubject: ACTION_SUBJECT.SYNCED_BLOCK,
255
- actionSubjectId: ACTION_SUBJECT_ID.REFERENCE_SYNCED_BLOCK_DELETE,
256
- attributes: {
257
- resourceId: syncBlock.attrs.resourceId,
258
- blockInstanceId: syncBlock.attrs.localId
259
- },
260
- eventType: EVENT_TYPE.OPERATIONAL
261
- });
239
+ const {
240
+ removed: syncBlockRemoved,
241
+ added: syncBlockAdded
242
+ } = trackSyncBlocks(node => node.type.name === 'syncBlock', tr, state);
243
+ syncBlockRemoved.forEach(syncBlock => {
244
+ var _api$analytics, _api$analytics$action;
245
+ api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : (_api$analytics$action = _api$analytics.actions) === null || _api$analytics$action === void 0 ? void 0 : _api$analytics$action.fireAnalyticsEvent({
246
+ action: ACTION.DELETED,
247
+ actionSubject: ACTION_SUBJECT.SYNCED_BLOCK,
248
+ actionSubjectId: ACTION_SUBJECT_ID.REFERENCE_SYNCED_BLOCK_DELETE,
249
+ attributes: {
250
+ resourceId: syncBlock.attrs.resourceId,
251
+ blockInstanceId: syncBlock.attrs.localId
252
+ },
253
+ eventType: EVENT_TYPE.OPERATIONAL
262
254
  });
263
- syncBlockAdded.forEach(syncBlock => {
264
- var _api$analytics2, _api$analytics2$actio;
265
- api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : (_api$analytics2$actio = _api$analytics2.actions) === null || _api$analytics2$actio === void 0 ? void 0 : _api$analytics2$actio.fireAnalyticsEvent({
266
- action: ACTION.INSERTED,
267
- actionSubject: ACTION_SUBJECT.SYNCED_BLOCK,
268
- actionSubjectId: ACTION_SUBJECT_ID.REFERENCE_SYNCED_BLOCK_CREATE,
269
- attributes: {
270
- resourceId: syncBlock.attrs.resourceId,
271
- blockInstanceId: syncBlock.attrs.localId
272
- },
273
- eventType: EVENT_TYPE.OPERATIONAL
274
- });
255
+ });
256
+ syncBlockAdded.forEach(syncBlock => {
257
+ var _api$analytics2, _api$analytics2$actio;
258
+ api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : (_api$analytics2$actio = _api$analytics2.actions) === null || _api$analytics2$actio === void 0 ? void 0 : _api$analytics2$actio.fireAnalyticsEvent({
259
+ action: ACTION.INSERTED,
260
+ actionSubject: ACTION_SUBJECT.SYNCED_BLOCK,
261
+ actionSubjectId: ACTION_SUBJECT_ID.REFERENCE_SYNCED_BLOCK_CREATE,
262
+ attributes: {
263
+ resourceId: syncBlock.attrs.resourceId,
264
+ blockInstanceId: syncBlock.attrs.localId
265
+ },
266
+ eventType: EVENT_TYPE.OPERATIONAL
275
267
  });
276
- }
277
- ;
268
+ });
278
269
  if (bodiedSyncBlockRemoved.length > 0) {
279
270
  confirmationTransactionRef.current = tr;
280
- return handleBodiedSyncBlockRemoval(bodiedSyncBlockRemoved, syncBlockStore, api, confirmationTransactionRef, fg('platform_synced_block_dogfooding') ? getDeleteReason(tr) : undefined);
271
+ return handleBodiedSyncBlockRemoval(bodiedSyncBlockRemoved, syncBlockStore, api, confirmationTransactionRef, getDeleteReason(tr));
281
272
  }
282
273
  if (bodiedSyncBlockAdded.length > 0) {
283
274
  if (Boolean(tr.getMeta(pmHistoryPluginKey))) {
@@ -3,6 +3,7 @@ import { ACTION, ACTION_SUBJECT_ID } from '@atlaskit/editor-common/analytics';
3
3
  import { Experience, EXPERIENCE_ID, ExperienceCheckDomMutation, ExperienceCheckTimeout, getNodeQuery, getPopupContainerFromEditorView, popupWithNestedElement } from '@atlaskit/editor-common/experiences';
4
4
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
5
5
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
6
+ import { fg } from '@atlaskit/platform-feature-flags';
6
7
  import { SYNCED_BLOCK_BUTTON_TEST_ID } from '../types';
7
8
  const TIMEOUT_DURATION = 30000;
8
9
  const pluginKey = new PluginKey('syncedBlockMenuAndToolbarExperience');
@@ -21,22 +22,76 @@ export const getMenuAndToolbarExperiencesPlugin = ({
21
22
  }
22
23
  return popupsTargetEl;
23
24
  };
24
- const createSourcePrimaryToolbarExperience = getCreateSourcePrimaryToolbarExperience({
25
- refs,
26
- dispatchAnalyticsEvent
25
+ const createSourcePrimaryToolbarExperience = new Experience(EXPERIENCE_ID.TOOLBAR_ACTION, {
26
+ action: ACTION.SYNCED_BLOCK_CREATE,
27
+ actionSubjectId: ACTION_SUBJECT_ID.PRIMARY_TOOLBAR,
28
+ dispatchAnalyticsEvent,
29
+ checks: [new ExperienceCheckTimeout({
30
+ durationMs: TIMEOUT_DURATION
31
+ }), syncedBlockAddedToDomCheck(refs)]
27
32
  });
28
- const createSourceBlockMenuExperience = getCreateSourceBlockMenuExperience({
29
- refs,
30
- dispatchAnalyticsEvent
33
+ const createSourceBlockMenuExperience = new Experience(EXPERIENCE_ID.MENU_ACTION, {
34
+ action: ACTION.SYNCED_BLOCK_CREATE,
35
+ actionSubjectId: ACTION_SUBJECT_ID.BLOCK_MENU,
36
+ dispatchAnalyticsEvent,
37
+ checks: [new ExperienceCheckTimeout({
38
+ durationMs: TIMEOUT_DURATION
39
+ }), syncedBlockAddedToDomCheck(refs)]
31
40
  });
32
- const createSourceQuickInsertMenuExperience = getCreateSourceQuickInsertMenuExperience({
33
- refs,
34
- dispatchAnalyticsEvent
41
+ const createSourceQuickInsertMenuExperience = new Experience(EXPERIENCE_ID.MENU_ACTION, {
42
+ action: ACTION.SYNCED_BLOCK_CREATE,
43
+ actionSubjectId: ACTION_SUBJECT_ID.QUICK_INSERT,
44
+ dispatchAnalyticsEvent,
45
+ checks: [new ExperienceCheckTimeout({
46
+ durationMs: TIMEOUT_DURATION
47
+ }), syncedBlockAddedToDomCheck(refs)]
35
48
  });
36
- const deleteReferenceSyncedBlockExperience = getDeleteReferenceSyncedBlockToolbarExperience({
37
- refs,
38
- dispatchAnalyticsEvent
49
+ const deleteReferenceSyncedBlockExperience = new Experience(EXPERIENCE_ID.TOOLBAR_ACTION, {
50
+ action: ACTION.REFERENCE_SYNCED_BLOCK_DELETE,
51
+ actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_TOOLBAR,
52
+ dispatchAnalyticsEvent,
53
+ checks: [new ExperienceCheckTimeout({
54
+ durationMs: TIMEOUT_DURATION
55
+ }), referenceSyncBlockRemovedFromDomCheck(refs)]
39
56
  });
57
+ let unsyncReferenceSyncedBlockExperience;
58
+ let unsyncSourceSyncedBlockExperience;
59
+ let deleteSourceSyncedBlockExperience;
60
+ let syncedLocationsExperience;
61
+ if (fg('platform_synced_block_patch_1')) {
62
+ unsyncReferenceSyncedBlockExperience = new Experience(EXPERIENCE_ID.TOOLBAR_ACTION, {
63
+ action: ACTION.REFERENCE_SYNCED_BLOCK_UNSYNC,
64
+ actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_TOOLBAR,
65
+ dispatchAnalyticsEvent,
66
+ checks: [new ExperienceCheckTimeout({
67
+ durationMs: TIMEOUT_DURATION
68
+ }), referenceSyncBlockRemovedFromDomCheck(refs)]
69
+ });
70
+ unsyncSourceSyncedBlockExperience = new Experience(EXPERIENCE_ID.TOOLBAR_ACTION, {
71
+ action: ACTION.SYNCED_BLOCK_UNSYNC,
72
+ actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_TOOLBAR,
73
+ dispatchAnalyticsEvent,
74
+ checks: [new ExperienceCheckTimeout({
75
+ durationMs: TIMEOUT_DURATION
76
+ }), syncBlockDeleteConfirmationModalAddedCheck(refs)]
77
+ });
78
+ deleteSourceSyncedBlockExperience = new Experience(EXPERIENCE_ID.TOOLBAR_ACTION, {
79
+ action: ACTION.SYNCED_BLOCK_DELETE,
80
+ actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_TOOLBAR,
81
+ dispatchAnalyticsEvent,
82
+ checks: [new ExperienceCheckTimeout({
83
+ durationMs: TIMEOUT_DURATION
84
+ }), syncBlockDeleteConfirmationModalAddedCheck(refs)]
85
+ });
86
+ syncedLocationsExperience = new Experience(EXPERIENCE_ID.TOOLBAR_ACTION, {
87
+ action: ACTION.SYNCED_BLOCK_VIEW_SYNCED_LOCATIONS,
88
+ actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_TOOLBAR,
89
+ dispatchAnalyticsEvent,
90
+ checks: [new ExperienceCheckTimeout({
91
+ durationMs: TIMEOUT_DURATION
92
+ }), syncedLocationsDropdownOpenedCheck(refs)]
93
+ });
94
+ }
40
95
  const unbindClickListener = bind(document, {
41
96
  type: 'click',
42
97
  listener: event => {
@@ -52,13 +107,24 @@ export const getMenuAndToolbarExperiencesPlugin = ({
52
107
  if (!isSyncedBlockButtonId(testId)) {
53
108
  return;
54
109
  }
110
+ if (button.disabled) {
111
+ return;
112
+ }
55
113
  handleButtonClick({
56
114
  testId,
115
+ button,
57
116
  createSourcePrimaryToolbarExperience,
58
117
  createSourceBlockMenuExperience,
59
118
  createSourceQuickInsertMenuExperience,
60
- deleteReferenceSyncedBlockExperience
119
+ deleteReferenceSyncedBlockExperience,
120
+ unsyncReferenceSyncedBlockExperience,
121
+ unsyncSourceSyncedBlockExperience,
122
+ deleteSourceSyncedBlockExperience,
123
+ syncedLocationsExperience
61
124
  });
125
+ },
126
+ options: {
127
+ capture: true
62
128
  }
63
129
  });
64
130
  const unbindKeydownListener = bind(document, {
@@ -89,6 +155,7 @@ export const getMenuAndToolbarExperiencesPlugin = ({
89
155
  editorViewEl = editorView.dom;
90
156
  return {
91
157
  destroy: () => {
158
+ var _deleteSourceSyncedBl, _unsyncReferenceSynce, _unsyncSourceSyncedBl, _syncedLocationsExper;
92
159
  createSourcePrimaryToolbarExperience.abort({
93
160
  reason: 'editorDestroyed'
94
161
  });
@@ -101,6 +168,18 @@ export const getMenuAndToolbarExperiencesPlugin = ({
101
168
  deleteReferenceSyncedBlockExperience.abort({
102
169
  reason: 'editorDestroyed'
103
170
  });
171
+ (_deleteSourceSyncedBl = deleteSourceSyncedBlockExperience) === null || _deleteSourceSyncedBl === void 0 ? void 0 : _deleteSourceSyncedBl.abort({
172
+ reason: 'editorDestroyed'
173
+ });
174
+ (_unsyncReferenceSynce = unsyncReferenceSyncedBlockExperience) === null || _unsyncReferenceSynce === void 0 ? void 0 : _unsyncReferenceSynce.abort({
175
+ reason: 'editorDestroyed'
176
+ });
177
+ (_unsyncSourceSyncedBl = unsyncSourceSyncedBlockExperience) === null || _unsyncSourceSyncedBl === void 0 ? void 0 : _unsyncSourceSyncedBl.abort({
178
+ reason: 'editorDestroyed'
179
+ });
180
+ (_syncedLocationsExper = syncedLocationsExperience) === null || _syncedLocationsExper === void 0 ? void 0 : _syncedLocationsExper.abort({
181
+ reason: 'editorDestroyed'
182
+ });
104
183
  unbindClickListener();
105
184
  unbindKeydownListener();
106
185
  }
@@ -108,80 +187,64 @@ export const getMenuAndToolbarExperiencesPlugin = ({
108
187
  }
109
188
  });
110
189
  };
111
- const getCreateSourcePrimaryToolbarExperience = ({
112
- refs,
113
- dispatchAnalyticsEvent
114
- }) => {
115
- return new Experience(EXPERIENCE_ID.TOOLBAR_ACTION, {
116
- action: ACTION.SYNCED_BLOCK_CREATE,
117
- actionSubjectId: ACTION_SUBJECT_ID.PRIMARY_TOOLBAR,
118
- dispatchAnalyticsEvent,
119
- checks: [new ExperienceCheckTimeout({
120
- durationMs: TIMEOUT_DURATION
121
- }), syncedBlockAddedToDomCheck(refs)]
122
- });
123
- };
124
- const getCreateSourceBlockMenuExperience = ({
125
- refs,
126
- dispatchAnalyticsEvent
127
- }) => {
128
- return new Experience(EXPERIENCE_ID.MENU_ACTION, {
129
- action: ACTION.SYNCED_BLOCK_CREATE,
130
- actionSubjectId: ACTION_SUBJECT_ID.BLOCK_MENU,
131
- dispatchAnalyticsEvent,
132
- checks: [new ExperienceCheckTimeout({
133
- durationMs: TIMEOUT_DURATION
134
- }), syncedBlockAddedToDomCheck(refs)]
135
- });
136
- };
137
- const getCreateSourceQuickInsertMenuExperience = ({
138
- refs,
139
- dispatchAnalyticsEvent
140
- }) => {
141
- return new Experience(EXPERIENCE_ID.MENU_ACTION, {
142
- action: ACTION.SYNCED_BLOCK_CREATE,
143
- actionSubjectId: ACTION_SUBJECT_ID.QUICK_INSERT,
144
- dispatchAnalyticsEvent,
145
- checks: [new ExperienceCheckTimeout({
146
- durationMs: TIMEOUT_DURATION
147
- }), syncedBlockAddedToDomCheck(refs)]
148
- });
149
- };
150
- const getDeleteReferenceSyncedBlockToolbarExperience = ({
151
- refs,
152
- dispatchAnalyticsEvent
153
- }) => {
154
- return new Experience(EXPERIENCE_ID.TOOLBAR_ACTION, {
155
- action: ACTION.REFERENCE_SYNCED_BLOCK_DELETE,
156
- actionSubjectId: ACTION_SUBJECT_ID.SYNCED_BLOCK_TOOLBAR,
157
- dispatchAnalyticsEvent,
158
- checks: [new ExperienceCheckTimeout({
159
- durationMs: TIMEOUT_DURATION
160
- }), referenceSyncBlockRemovedFromDomCheck(refs)]
161
- });
162
- };
163
190
  const isSyncedBlockButtonId = value => {
164
191
  return !!value && syncedBlockButtonIds.has(value);
165
192
  };
166
193
  const handleButtonClick = ({
167
194
  testId,
195
+ button,
168
196
  createSourcePrimaryToolbarExperience,
169
197
  createSourceBlockMenuExperience,
170
198
  createSourceQuickInsertMenuExperience,
171
- deleteReferenceSyncedBlockExperience
199
+ deleteReferenceSyncedBlockExperience,
200
+ unsyncReferenceSyncedBlockExperience,
201
+ unsyncSourceSyncedBlockExperience,
202
+ deleteSourceSyncedBlockExperience,
203
+ syncedLocationsExperience
172
204
  }) => {
173
205
  switch (testId) {
174
206
  case SYNCED_BLOCK_BUTTON_TEST_ID.primaryToolbarCreate:
175
- createSourcePrimaryToolbarExperience.start();
207
+ createSourcePrimaryToolbarExperience.start({
208
+ forceRestart: true
209
+ });
176
210
  break;
177
211
  case SYNCED_BLOCK_BUTTON_TEST_ID.blockMenuCreate:
178
- createSourceBlockMenuExperience.start();
212
+ createSourceBlockMenuExperience.start({
213
+ forceRestart: true
214
+ });
179
215
  break;
180
216
  case SYNCED_BLOCK_BUTTON_TEST_ID.quickInsertCreate:
181
- createSourceQuickInsertMenuExperience.start();
217
+ createSourceQuickInsertMenuExperience.start({
218
+ forceRestart: true
219
+ });
182
220
  break;
183
221
  case SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarReferenceDelete:
184
- deleteReferenceSyncedBlockExperience.start();
222
+ deleteReferenceSyncedBlockExperience.start({
223
+ forceRestart: true
224
+ });
225
+ break;
226
+ case SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarReferenceUnsync:
227
+ unsyncReferenceSyncedBlockExperience === null || unsyncReferenceSyncedBlockExperience === void 0 ? void 0 : unsyncReferenceSyncedBlockExperience.start({
228
+ forceRestart: true
229
+ });
230
+ break;
231
+ case SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarSourceUnsync:
232
+ unsyncSourceSyncedBlockExperience === null || unsyncSourceSyncedBlockExperience === void 0 ? void 0 : unsyncSourceSyncedBlockExperience.start({
233
+ forceRestart: true
234
+ });
235
+ break;
236
+ case SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarSourceDelete:
237
+ deleteSourceSyncedBlockExperience === null || deleteSourceSyncedBlockExperience === void 0 ? void 0 : deleteSourceSyncedBlockExperience.start({
238
+ forceRestart: true
239
+ });
240
+ break;
241
+ case SYNCED_BLOCK_BUTTON_TEST_ID.syncedBlockToolbarSyncedLocationsTrigger:
242
+ // Only track when opening the dropdown
243
+ if (button.getAttribute('aria-pressed') === 'false') {
244
+ syncedLocationsExperience === null || syncedLocationsExperience === void 0 ? void 0 : syncedLocationsExperience.start({
245
+ forceRestart: true
246
+ });
247
+ }
185
248
  break;
186
249
  default:
187
250
  {
@@ -258,4 +321,76 @@ const isSyncBlockRemovedInMutation = ({
258
321
  }) => {
259
322
  return type === 'childList' && [...removedNodes].some(isSyncBlockWithinNode);
260
323
  };
261
- const isSyncBlockWithinNode = node => getNodeQuery('[data-prosemirror-node-name="syncBlock"]')(node);
324
+ const isSyncBlockWithinNode = node => getNodeQuery('[data-prosemirror-node-name="syncBlock"]')(node);
325
+ const syncBlockDeleteConfirmationModalAddedCheck = refs => new ExperienceCheckDomMutation({
326
+ onDomMutation: ({
327
+ mutations
328
+ }) => {
329
+ if (mutations.some(isDeleteConfirmationModalAddedInMutation)) {
330
+ return {
331
+ status: 'success'
332
+ };
333
+ }
334
+ return undefined;
335
+ },
336
+ observeConfig: () => {
337
+ return {
338
+ target: document.body,
339
+ options: {
340
+ childList: true,
341
+ subtree: true
342
+ }
343
+ };
344
+ }
345
+ });
346
+ const isDeleteConfirmationModalAddedInMutation = ({
347
+ type,
348
+ addedNodes
349
+ }) => {
350
+ return type === 'childList' && [...addedNodes].some(isDeleteConfirmationModalWithinNode);
351
+ };
352
+ const isDeleteConfirmationModalWithinNode = node => getNodeQuery('[data-testid="sync-block-delete-confirmation"]')(node);
353
+ const syncedLocationsDropdownOpenedCheck = refs => new ExperienceCheckDomMutation({
354
+ onDomMutation: ({
355
+ mutations
356
+ }) => {
357
+ if (mutations.some(isSyncedLocationsDropdownErrorInMutation)) {
358
+ return {
359
+ status: 'failure'
360
+ };
361
+ }
362
+ if (mutations.some(isSyncedLocationsDropdownAddedInMutation)) {
363
+ return {
364
+ status: 'success'
365
+ };
366
+ }
367
+ return undefined;
368
+ },
369
+ observeConfig: () => {
370
+ return {
371
+ target: document.body,
372
+ options: {
373
+ childList: true,
374
+ subtree: true
375
+ }
376
+ };
377
+ }
378
+ });
379
+ const isSyncedLocationsDropdownAddedInMutation = ({
380
+ type,
381
+ addedNodes
382
+ }) => {
383
+ return type === 'childList' && [...addedNodes].some(isSyncedLocationsDropdownWithinNode);
384
+ };
385
+ const isSyncedLocationsDropdownErrorInMutation = ({
386
+ type,
387
+ addedNodes
388
+ }) => {
389
+ return type === 'childList' && [...addedNodes].some(isSyncedLocationsDropdownErrorWithinNode);
390
+ };
391
+ const isSyncedLocationsDropdownWithinNode = node => {
392
+ return !!(getNodeQuery('[data-testid="synced-locations-dropdown-content"]')(node) || getNodeQuery('[data-testid="synced-locations-dropdown-content-no-results"]')(node));
393
+ };
394
+ const isSyncedLocationsDropdownErrorWithinNode = node => {
395
+ return !!getNodeQuery('[data-testid="synced-locations-dropdown-content-error"]')(node);
396
+ };
@@ -1,6 +1,5 @@
1
1
  import { ReplaceAroundStep, ReplaceStep } from '@atlaskit/editor-prosemirror/transform';
2
2
  import { findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
3
- import { fg } from '@atlaskit/platform-feature-flags';
4
3
  export const trackSyncBlocks = (predicate, tr, state) => {
5
4
  const removed = {};
6
5
  const added = {};
@@ -20,7 +19,7 @@ export const trackSyncBlocks = (predicate, tr, state) => {
20
19
  from,
21
20
  to
22
21
  } = step;
23
- const docAtStep = fg('platform_synced_block_dogfooding') ? tr.docs[idx] : state.doc;
22
+ const docAtStep = tr.docs[idx];
24
23
  let hasChange = false;
25
24
  if (from !== to) {
26
25
  step.getMap().forEach((oldStart, oldEnd) => {
@@ -1,9 +1,6 @@
1
1
  import { expandSelectionToBlockRange } from '@atlaskit/editor-common/selection';
2
2
  import { Fragment } from '@atlaskit/editor-prosemirror/model';
3
- import { TextSelection } from '@atlaskit/editor-prosemirror/state';
4
3
  import { findParentNodeOfType, findSelectedNodeOfType } from '@atlaskit/editor-prosemirror/utils';
5
- import { CellSelection, findTable } from '@atlaskit/editor-tables';
6
- import { fg } from '@atlaskit/platform-feature-flags';
7
4
  export const findSyncBlock = (schema, selection) => {
8
5
  const {
9
6
  syncBlock
@@ -28,50 +25,6 @@ const UNSUPPORTED_NODE_TYPES = new Set(['inlineExtension', 'extension', 'bodiedE
28
25
  * or false if conversion is not possible
29
26
  */
30
27
  export const canBeConvertedToSyncBlock = selection => {
31
- return fg('platform_synced_block_dogfooding') ? canBeConvertedToSyncBlockNew(selection) : canBeConvertedToSyncBlockOld(selection);
32
- };
33
- export const canBeConvertedToSyncBlockOld = selection => {
34
- const schema = selection.$from.doc.type.schema;
35
- const {
36
- nodes
37
- } = schema;
38
- let from = selection.from;
39
- let to = selection.to;
40
- let contentToInclude = selection.content().content;
41
- if (selection instanceof CellSelection) {
42
- const table = findTable(selection);
43
- if (!table) {
44
- return false;
45
- }
46
- contentToInclude = Fragment.from([table.node]);
47
- from = table.pos;
48
- to = table.pos + table.node.nodeSize;
49
- } else if (selection instanceof TextSelection) {
50
- const trueParent = findParentNodeOfType([nodes.bulletList, nodes.orderedList, nodes.taskList, nodes.blockquote])(selection);
51
- if (trueParent) {
52
- contentToInclude = Fragment.from([trueParent.node]);
53
- from = trueParent.pos;
54
- to = trueParent.pos + trueParent.node.nodeSize;
55
- }
56
- }
57
- let canBeConverted = true;
58
- selection.$from.doc.nodesBetween(from, to, node => {
59
- if (UNSUPPORTED_NODE_TYPES.has(node.type.name)) {
60
- canBeConverted = false;
61
- return false;
62
- }
63
- });
64
- if (!canBeConverted) {
65
- return false;
66
- }
67
- contentToInclude = removeBreakoutMarks(contentToInclude);
68
- return {
69
- contentToInclude,
70
- from,
71
- to
72
- };
73
- };
74
- export const canBeConvertedToSyncBlockNew = selection => {
75
28
  const {
76
29
  $from,
77
30
  range
@@ -4,7 +4,6 @@ import { blockTypeMessages } from '@atlaskit/editor-common/messages';
4
4
  import { IconSyncBlock } from '@atlaskit/editor-common/quick-insert';
5
5
  import { SyncBlockStoreManager } from '@atlaskit/editor-synced-block-provider';
6
6
  import Lozenge from '@atlaskit/lozenge';
7
- import { fg } from '@atlaskit/platform-feature-flags';
8
7
  import { flushBodiedSyncBlocks, flushSyncBlocks } from './editor-actions';
9
8
  import { copySyncedBlockReferenceToClipboardEditorCommand, createSyncedBlock } from './editor-commands';
10
9
  import { createPlugin, syncedBlockPluginKey } from './pm-plugins/main';
@@ -41,7 +40,7 @@ export const syncedBlockPlugin = ({
41
40
  return [{
42
41
  name: 'syncedBlockPlugin',
43
42
  plugin: params => createPlugin(config, params, syncBlockStore, api)
44
- }, ...(fg('platform_synced_block_dogfooding') ? [{
43
+ }, {
45
44
  name: 'menuAndToolbarExperiencesPlugin',
46
45
  plugin: () => getMenuAndToolbarExperiencesPlugin({
47
46
  refs,
@@ -50,10 +49,10 @@ export const syncedBlockPlugin = ({
50
49
  return api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : (_api$analytics2$actio = _api$analytics2.actions) === null || _api$analytics2$actio === void 0 ? void 0 : _api$analytics2$actio.fireAnalyticsEvent(payload);
51
50
  }
52
51
  })
53
- }] : [])];
52
+ }];
54
53
  },
55
54
  commands: {
56
- copySyncedBlockReferenceToClipboard: () => copySyncedBlockReferenceToClipboardEditorCommand(syncBlockStore, api),
55
+ copySyncedBlockReferenceToClipboard: inputMethod => copySyncedBlockReferenceToClipboardEditorCommand(syncBlockStore, inputMethod, api),
57
56
  insertSyncedBlock: () => ({
58
57
  tr
59
58
  }) => {
@@ -106,7 +105,7 @@ export const syncedBlockPlugin = ({
106
105
  fireAnalyticsEvent: api === null || api === void 0 ? void 0 : (_api$analytics4 = api.analytics) === null || _api$analytics4 === void 0 ? void 0 : _api$analytics4.actions.fireAnalyticsEvent
107
106
  });
108
107
  },
109
- testId: fg('platform_synced_block_dogfooding') ? SYNCED_BLOCK_BUTTON_TEST_ID.quickInsertCreate : undefined
108
+ testId: SYNCED_BLOCK_BUTTON_TEST_ID.quickInsertCreate
110
109
  }];
111
110
  },
112
111
  floatingToolbar: (state, intl) => getToolbarConfig(state, intl, api, syncBlockStore)
@@ -11,5 +11,9 @@ export const SYNCED_BLOCK_BUTTON_TEST_ID = {
11
11
  primaryToolbarCreate: 'create-synced-block-toolbar-btn',
12
12
  blockMenuCreate: 'create-synced-block-block-menu-btn',
13
13
  quickInsertCreate: 'create-synced-block-quick-insert-btn',
14
- syncedBlockToolbarReferenceDelete: 'reference-synced-block-delete-btn'
14
+ syncedBlockToolbarReferenceDelete: 'reference-synced-block-delete-btn',
15
+ syncedBlockToolbarSourceDelete: 'source-synced-block-delete-btn',
16
+ syncedBlockToolbarReferenceUnsync: 'reference-synced-block-unsync-btn',
17
+ syncedBlockToolbarSourceUnsync: 'source-synced-block-unsync-btn',
18
+ syncedBlockToolbarSyncedLocationsTrigger: 'synced-block-synced-locations-dropdown--trigger'
15
19
  };
@@ -1,5 +1,6 @@
1
1
  import React, { useMemo } from 'react';
2
2
  import { useIntl } from 'react-intl-next';
3
+ import { INPUT_METHOD } from '@atlaskit/editor-common/analytics';
3
4
  import { useSharedPluginStateWithSelector } from '@atlaskit/editor-common/hooks';
4
5
  import { blockMenuMessages } from '@atlaskit/editor-common/messages';
5
6
  import { isOfflineMode } from '@atlaskit/editor-plugin-connectivity';
@@ -66,7 +67,7 @@ const CopySyncedBlockDropdownItem = ({
66
67
  });
67
68
  const onClick = () => {
68
69
  var _api$core3, _api$core4, _api$blockControls2, _api$blockControls2$c;
69
- 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());
70
+ 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));
70
71
  api === null || api === void 0 ? void 0 : (_api$core4 = api.core) === null || _api$core4 === void 0 ? void 0 : _api$core4.actions.execute(api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : (_api$blockControls2$c = _api$blockControls2.commands) === null || _api$blockControls2$c === void 0 ? void 0 : _api$blockControls2$c.toggleBlockMenu({
71
72
  closeMenu: true
72
73
  }));