@atlaskit/editor-plugin-synced-block 4.3.9 → 4.3.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @atlaskit/editor-plugin-synced-block
2
2
 
3
+ ## 4.3.10
4
+
5
+ ### Patch Changes
6
+
7
+ - [`99387f7d6303b`](https://bitbucket.org/atlassian/atlassian-frontend-monorepo/commits/99387f7d6303b) -
8
+ [ux] [EDITOR-2767] Implement bodiedSyncBlock creation/deletion undo/redo
9
+ - Updated dependencies
10
+
3
11
  ## 4.3.9
4
12
 
5
13
  ### Patch Changes
@@ -7,6 +7,7 @@ exports.syncedBlockPluginKey = exports.createPlugin = void 0;
7
7
  var _safePlugin = require("@atlaskit/editor-common/safe-plugin");
8
8
  var _selection = require("@atlaskit/editor-common/selection");
9
9
  var _syncBlock = require("@atlaskit/editor-common/sync-block");
10
+ var _utils = require("@atlaskit/editor-common/utils");
10
11
  var _state = require("@atlaskit/editor-prosemirror/state");
11
12
  var _view = require("@atlaskit/editor-prosemirror/view");
12
13
  var _editorSyncedBlockProvider = require("@atlaskit/editor-synced-block-provider");
@@ -15,7 +16,10 @@ var _lazySyncedBlock = require("../nodeviews/lazySyncedBlock");
15
16
  var _types = require("../types");
16
17
  var _ignoreDomEvent = require("./utils/ignore-dom-event");
17
18
  var _selectionDecorations = require("./utils/selection-decorations");
18
- var _trackSyncBlocks3 = require("./utils/track-sync-blocks");
19
+ var _trackSyncBlocks4 = require("./utils/track-sync-blocks");
20
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
21
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
22
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
19
23
  var syncedBlockPluginKey = exports.syncedBlockPluginKey = new _state.PluginKey('syncedBlockPlugin');
20
24
  var createPlugin = exports.createPlugin = function createPlugin(options, pmPluginFactoryParams, syncBlockStore, api) {
21
25
  var _ref = options || {},
@@ -127,7 +131,7 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
127
131
  if (!tr.docChanged || !(syncBlockStore !== null && syncBlockStore !== void 0 && syncBlockStore.sourceManager.requireConfirmationBeforeDelete()) && !syncBlockStore.sourceManager.hasPendingCreation() || Boolean(tr.getMeta('isRemote')) || Boolean(tr.getMeta('isCommitSyncBlockCreation')) || !isOffline && isConfirmedSyncBlockDeletion) {
128
132
  return true;
129
133
  }
130
- var _trackSyncBlocks = (0, _trackSyncBlocks3.trackSyncBlocks)(syncBlockStore.sourceManager.isSourceBlock, tr, state),
134
+ var _trackSyncBlocks = (0, _trackSyncBlocks4.trackSyncBlocks)(syncBlockStore.sourceManager.isSourceBlock, tr, state),
131
135
  bodiedSyncBlockRemoved = _trackSyncBlocks.removed,
132
136
  bodiedSyncBlockAdded = _trackSyncBlocks.added;
133
137
  if (!isOffline) {
@@ -136,10 +140,19 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
136
140
  // we block the transaction here, and wait for user confirmation to proceed with deletion.
137
141
  // See editor-common/src/sync-block/sync-block-store-manager.ts for how we handle user confirmation and
138
142
  // proceed with deletion.
139
- syncBlockStore.sourceManager.deleteSyncBlocksWithConfirmation(tr, bodiedSyncBlockRemoved);
143
+ syncBlockStore.sourceManager.deleteSyncBlocksWithConfirmation(tr, bodiedSyncBlockRemoved.map(function (node) {
144
+ return node.attrs;
145
+ }));
140
146
  return false;
141
147
  }
142
148
  if (bodiedSyncBlockAdded.length > 0) {
149
+ if (Boolean(tr.getMeta(_utils.pmHistoryPluginKey))) {
150
+ // We don't allow bodiedSyncBlock creation via redo, however, we need to return true here to let transaction through so history can be updated properly.
151
+ // If we simply returns false, creation from redo is blocked as desired, but this results in editor showing redo as possible even though it's not.
152
+ // After true is returned here and the node is created, we delete the node in the filterTransaction immediately, which cancels out the creation
153
+ return true;
154
+ }
155
+
143
156
  // If there is bodiedSyncBlock node addition and it's waiting for the result of saving the node to backend (syncBlockStore.hasPendingCreation()),
144
157
  // we need to intercept the transaction and save it in insert callback so that we only insert it to the document when backend call if backend call is successful
145
158
  // The callback will be evoked by in SourceSyncBlockStoreManager.commitPendingCreation
@@ -153,18 +166,19 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
153
166
  return false;
154
167
  }
155
168
  } else {
156
- // Disable (bodied)syncBlock node deletion/creation/edition in offline mode and trigger an error flag instead
157
- var _trackSyncBlocks2 = (0, _trackSyncBlocks3.trackSyncBlocks)(function (node) {
169
+ var _trackSyncBlocks2 = (0, _trackSyncBlocks4.trackSyncBlocks)(function (node) {
158
170
  return node.type.name === 'syncBlock';
159
171
  }, tr, state),
160
172
  syncBlockRemoved = _trackSyncBlocks2.removed,
161
173
  syncBlockAdded = _trackSyncBlocks2.added;
162
174
  var errorFlag = false;
175
+
176
+ // Disable (bodied)syncBlock node deletion/creation/edition in offline mode and trigger an error flag instead
163
177
  if (isConfirmedSyncBlockDeletion || bodiedSyncBlockRemoved.length > 0 || syncBlockRemoved.length > 0) {
164
178
  errorFlag = _types.FLAG_ID.CANNOT_DELETE_WHEN_OFFLINE;
165
179
  } else if (bodiedSyncBlockAdded.length > 0 || syncBlockAdded.length > 0) {
166
180
  errorFlag = _types.FLAG_ID.CANNOT_CREATE_WHEN_OFFLINE;
167
- } else if ((0, _trackSyncBlocks3.hasEditInSyncBlock)(tr, state)) {
181
+ } else if ((0, _trackSyncBlocks4.hasEditInSyncBlock)(tr, state)) {
168
182
  errorFlag = _types.FLAG_ID.CANNOT_EDIT_WHEN_OFFLINE;
169
183
  }
170
184
  if (errorFlag) {
@@ -183,7 +197,7 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
183
197
  return true;
184
198
  },
185
199
  // @ts-ignore - Workaround for help-center local consumption
186
- appendTransaction: function appendTransaction(trs, _oldState, newState) {
200
+ appendTransaction: function appendTransaction(trs, oldState, newState) {
187
201
  trs
188
202
  // @ts-ignore - Workaround for help-center local consumption
189
203
  .filter(function (tr) {
@@ -193,6 +207,41 @@ var createPlugin = exports.createPlugin = function createPlugin(options, pmPlugi
193
207
  .forEach(function (tr) {
194
208
  syncBlockStore === null || syncBlockStore === void 0 || syncBlockStore.sourceManager.rebaseTransaction(tr, newState);
195
209
  });
210
+ var _iterator = _createForOfIteratorHelper(trs),
211
+ _step;
212
+ try {
213
+ var _loop = function _loop() {
214
+ var tr = _step.value;
215
+ if (!tr.getMeta(_utils.pmHistoryPluginKey)) {
216
+ return 0; // continue
217
+ }
218
+ var _trackSyncBlocks3 = (0, _trackSyncBlocks4.trackSyncBlocks)(syncBlockStore.sourceManager.isSourceBlock, tr, oldState),
219
+ added = _trackSyncBlocks3.added;
220
+ if (added.length > 0) {
221
+ // Delete bodiedSyncBlock if it's originated from history, i.e. redo creation
222
+ // See filterTransaction above for more details
223
+ var _tr = newState.tr;
224
+ added.forEach(function (node) {
225
+ if (node.from !== undefined && node.to !== undefined) {
226
+ _tr.delete(node.from, node.to);
227
+ }
228
+ });
229
+ return {
230
+ v: _tr
231
+ };
232
+ }
233
+ },
234
+ _ret;
235
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
236
+ _ret = _loop();
237
+ if (_ret === 0) continue;
238
+ if (_ret) return _ret.v;
239
+ }
240
+ } catch (err) {
241
+ _iterator.e(err);
242
+ } finally {
243
+ _iterator.f();
244
+ }
196
245
  return null;
197
246
  }
198
247
  });
@@ -33,7 +33,7 @@ var trackSyncBlocks = exports.trackSyncBlocks = function trackSyncBlocks(predica
33
33
  step.getMap().forEach(function (oldStart, oldEnd) {
34
34
  if (oldStart !== oldEnd && !hasChange) {
35
35
  var deletedSlice = state.doc.slice(Math.max(0, oldStart), Math.min(state.doc.content.size, oldEnd));
36
- deletedSlice.content.forEach(function (node, _, index) {
36
+ deletedSlice.content.forEach(function (node) {
37
37
  if (hasChange) {
38
38
  return;
39
39
  }
@@ -64,13 +64,19 @@ var trackSyncBlocks = exports.trackSyncBlocks = function trackSyncBlocks(predica
64
64
  oldDoc.content.forEach(function (node) {
65
65
  if (predicate(node)) {
66
66
  var syncBlockAttr = node.attrs;
67
- syncBlockMapOld[syncBlockAttr.localId] = syncBlockAttr;
67
+ syncBlockMapOld[syncBlockAttr.localId] = {
68
+ attrs: syncBlockAttr
69
+ };
68
70
  }
69
71
  });
70
- newDoc.content.forEach(function (node) {
72
+ newDoc.content.forEach(function (node, offset) {
71
73
  if (predicate(node)) {
72
74
  var syncBlockAttr = node.attrs;
73
- syncBlockMapNew[syncBlockAttr.localId] = syncBlockAttr;
75
+ syncBlockMapNew[syncBlockAttr.localId] = {
76
+ attrs: syncBlockAttr,
77
+ from: offset,
78
+ to: offset + node.nodeSize
79
+ };
74
80
  }
75
81
  });
76
82
 
@@ -60,7 +60,8 @@ var DeleteConfirmationModal = exports.DeleteConfirmationModal = function DeleteC
60
60
  };
61
61
  }, [syncBlockStoreManager, confirmationCallback]);
62
62
  return /*#__PURE__*/_react.default.createElement(_modalDialog.ModalTransition, null, isOpen && /*#__PURE__*/_react.default.createElement(_modalDialog.default, {
63
- onClose: handleClose(false)
63
+ onClose: handleClose(false),
64
+ testId: "sync-block-delete-confirmation"
64
65
  }, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalHeader, {
65
66
  hasCloseButton: true
66
67
  }, /*#__PURE__*/_react.default.createElement(_modalDialog.ModalTitle, {
@@ -1,6 +1,7 @@
1
1
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
2
  import { createSelectionClickHandler } from '@atlaskit/editor-common/selection';
3
3
  import { BodiedSyncBlockSharedCssClassName, SyncBlockStateCssClassName } from '@atlaskit/editor-common/sync-block';
4
+ import { pmHistoryPluginKey } from '@atlaskit/editor-common/utils';
4
5
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
5
6
  import { DecorationSet, Decoration } from '@atlaskit/editor-prosemirror/view';
6
7
  import { convertPMNodesToSyncBlockNodes } from '@atlaskit/editor-synced-block-provider';
@@ -131,10 +132,17 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
131
132
  // we block the transaction here, and wait for user confirmation to proceed with deletion.
132
133
  // See editor-common/src/sync-block/sync-block-store-manager.ts for how we handle user confirmation and
133
134
  // proceed with deletion.
134
- syncBlockStore.sourceManager.deleteSyncBlocksWithConfirmation(tr, bodiedSyncBlockRemoved);
135
+ syncBlockStore.sourceManager.deleteSyncBlocksWithConfirmation(tr, bodiedSyncBlockRemoved.map(node => node.attrs));
135
136
  return false;
136
137
  }
137
138
  if (bodiedSyncBlockAdded.length > 0) {
139
+ if (Boolean(tr.getMeta(pmHistoryPluginKey))) {
140
+ // We don't allow bodiedSyncBlock creation via redo, however, we need to return true here to let transaction through so history can be updated properly.
141
+ // If we simply returns false, creation from redo is blocked as desired, but this results in editor showing redo as possible even though it's not.
142
+ // After true is returned here and the node is created, we delete the node in the filterTransaction immediately, which cancels out the creation
143
+ return true;
144
+ }
145
+
138
146
  // If there is bodiedSyncBlock node addition and it's waiting for the result of saving the node to backend (syncBlockStore.hasPendingCreation()),
139
147
  // we need to intercept the transaction and save it in insert callback so that we only insert it to the document when backend call if backend call is successful
140
148
  // The callback will be evoked by in SourceSyncBlockStoreManager.commitPendingCreation
@@ -148,12 +156,13 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
148
156
  return false;
149
157
  }
150
158
  } else {
151
- // Disable (bodied)syncBlock node deletion/creation/edition in offline mode and trigger an error flag instead
152
159
  const {
153
160
  removed: syncBlockRemoved,
154
161
  added: syncBlockAdded
155
162
  } = trackSyncBlocks(node => node.type.name === 'syncBlock', tr, state);
156
163
  let errorFlag = false;
164
+
165
+ // Disable (bodied)syncBlock node deletion/creation/edition in offline mode and trigger an error flag instead
157
166
  if (isConfirmedSyncBlockDeletion || bodiedSyncBlockRemoved.length > 0 || syncBlockRemoved.length > 0) {
158
167
  errorFlag = FLAG_ID.CANNOT_DELETE_WHEN_OFFLINE;
159
168
  } else if (bodiedSyncBlockAdded.length > 0 || syncBlockAdded.length > 0) {
@@ -178,7 +187,7 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
178
187
  return true;
179
188
  },
180
189
  // @ts-ignore - Workaround for help-center local consumption
181
- appendTransaction: (trs, _oldState, newState) => {
190
+ appendTransaction: (trs, oldState, newState) => {
182
191
  trs
183
192
  // @ts-ignore - Workaround for help-center local consumption
184
193
  .filter(tr => tr.docChanged)
@@ -186,6 +195,25 @@ export const createPlugin = (options, pmPluginFactoryParams, syncBlockStore, api
186
195
  .forEach(tr => {
187
196
  syncBlockStore === null || syncBlockStore === void 0 ? void 0 : syncBlockStore.sourceManager.rebaseTransaction(tr, newState);
188
197
  });
198
+ for (const tr of trs) {
199
+ if (!tr.getMeta(pmHistoryPluginKey)) {
200
+ continue;
201
+ }
202
+ const {
203
+ added
204
+ } = trackSyncBlocks(syncBlockStore.sourceManager.isSourceBlock, tr, oldState);
205
+ if (added.length > 0) {
206
+ // Delete bodiedSyncBlock if it's originated from history, i.e. redo creation
207
+ // See filterTransaction above for more details
208
+ const tr = newState.tr;
209
+ added.forEach(node => {
210
+ if (node.from !== undefined && node.to !== undefined) {
211
+ tr.delete(node.from, node.to);
212
+ }
213
+ });
214
+ return tr;
215
+ }
216
+ }
189
217
  return null;
190
218
  }
191
219
  });
@@ -24,7 +24,7 @@ export const trackSyncBlocks = (predicate, tr, state) => {
24
24
  step.getMap().forEach((oldStart, oldEnd) => {
25
25
  if (oldStart !== oldEnd && !hasChange) {
26
26
  const deletedSlice = state.doc.slice(Math.max(0, oldStart), Math.min(state.doc.content.size, oldEnd));
27
- deletedSlice.content.forEach((node, _, index) => {
27
+ deletedSlice.content.forEach(node => {
28
28
  if (hasChange) {
29
29
  return;
30
30
  }
@@ -55,13 +55,19 @@ export const trackSyncBlocks = (predicate, tr, state) => {
55
55
  oldDoc.content.forEach(node => {
56
56
  if (predicate(node)) {
57
57
  const syncBlockAttr = node.attrs;
58
- syncBlockMapOld[syncBlockAttr.localId] = syncBlockAttr;
58
+ syncBlockMapOld[syncBlockAttr.localId] = {
59
+ attrs: syncBlockAttr
60
+ };
59
61
  }
60
62
  });
61
- newDoc.content.forEach(node => {
63
+ newDoc.content.forEach((node, offset) => {
62
64
  if (predicate(node)) {
63
65
  const syncBlockAttr = node.attrs;
64
- syncBlockMapNew[syncBlockAttr.localId] = syncBlockAttr;
66
+ syncBlockMapNew[syncBlockAttr.localId] = {
67
+ attrs: syncBlockAttr,
68
+ from: offset,
69
+ to: offset + node.nodeSize
70
+ };
65
71
  }
66
72
  });
67
73
 
@@ -45,7 +45,8 @@ export const DeleteConfirmationModal = ({
45
45
  };
46
46
  }, [syncBlockStoreManager, confirmationCallback]);
47
47
  return /*#__PURE__*/React.createElement(ModalTransition, null, isOpen && /*#__PURE__*/React.createElement(ModalDialog, {
48
- onClose: handleClose(false)
48
+ onClose: handleClose(false),
49
+ testId: "sync-block-delete-confirmation"
49
50
  }, /*#__PURE__*/React.createElement(ModalHeader, {
50
51
  hasCloseButton: true
51
52
  }, /*#__PURE__*/React.createElement(ModalTitle, {
@@ -1,6 +1,10 @@
1
+ function _createForOfIteratorHelper(r, e) { var t = "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (!t) { if (Array.isArray(r) || (t = _unsupportedIterableToArray(r)) || e && r && "number" == typeof r.length) { t && (r = t); var _n = 0, F = function F() {}; return { s: F, n: function n() { return _n >= r.length ? { done: !0 } : { done: !1, value: r[_n++] }; }, e: function e(r) { throw r; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var o, a = !0, u = !1; return { s: function s() { t = t.call(r); }, n: function n() { var r = t.next(); return a = r.done, r; }, e: function e(r) { u = !0, o = r; }, f: function f() { try { a || null == t.return || t.return(); } finally { if (u) throw o; } } }; }
2
+ function _unsupportedIterableToArray(r, a) { if (r) { if ("string" == typeof r) return _arrayLikeToArray(r, a); var t = {}.toString.call(r).slice(8, -1); return "Object" === t && r.constructor && (t = r.constructor.name), "Map" === t || "Set" === t ? Array.from(r) : "Arguments" === t || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t) ? _arrayLikeToArray(r, a) : void 0; } }
3
+ function _arrayLikeToArray(r, a) { (null == a || a > r.length) && (a = r.length); for (var e = 0, n = Array(a); e < a; e++) n[e] = r[e]; return n; }
1
4
  import { SafePlugin } from '@atlaskit/editor-common/safe-plugin';
2
5
  import { createSelectionClickHandler } from '@atlaskit/editor-common/selection';
3
6
  import { BodiedSyncBlockSharedCssClassName, SyncBlockStateCssClassName } from '@atlaskit/editor-common/sync-block';
7
+ import { pmHistoryPluginKey } from '@atlaskit/editor-common/utils';
4
8
  import { PluginKey } from '@atlaskit/editor-prosemirror/state';
5
9
  import { DecorationSet, Decoration } from '@atlaskit/editor-prosemirror/view';
6
10
  import { convertPMNodesToSyncBlockNodes } from '@atlaskit/editor-synced-block-provider';
@@ -130,10 +134,19 @@ export var createPlugin = function createPlugin(options, pmPluginFactoryParams,
130
134
  // we block the transaction here, and wait for user confirmation to proceed with deletion.
131
135
  // See editor-common/src/sync-block/sync-block-store-manager.ts for how we handle user confirmation and
132
136
  // proceed with deletion.
133
- syncBlockStore.sourceManager.deleteSyncBlocksWithConfirmation(tr, bodiedSyncBlockRemoved);
137
+ syncBlockStore.sourceManager.deleteSyncBlocksWithConfirmation(tr, bodiedSyncBlockRemoved.map(function (node) {
138
+ return node.attrs;
139
+ }));
134
140
  return false;
135
141
  }
136
142
  if (bodiedSyncBlockAdded.length > 0) {
143
+ if (Boolean(tr.getMeta(pmHistoryPluginKey))) {
144
+ // We don't allow bodiedSyncBlock creation via redo, however, we need to return true here to let transaction through so history can be updated properly.
145
+ // If we simply returns false, creation from redo is blocked as desired, but this results in editor showing redo as possible even though it's not.
146
+ // After true is returned here and the node is created, we delete the node in the filterTransaction immediately, which cancels out the creation
147
+ return true;
148
+ }
149
+
137
150
  // If there is bodiedSyncBlock node addition and it's waiting for the result of saving the node to backend (syncBlockStore.hasPendingCreation()),
138
151
  // we need to intercept the transaction and save it in insert callback so that we only insert it to the document when backend call if backend call is successful
139
152
  // The callback will be evoked by in SourceSyncBlockStoreManager.commitPendingCreation
@@ -147,13 +160,14 @@ export var createPlugin = function createPlugin(options, pmPluginFactoryParams,
147
160
  return false;
148
161
  }
149
162
  } else {
150
- // Disable (bodied)syncBlock node deletion/creation/edition in offline mode and trigger an error flag instead
151
163
  var _trackSyncBlocks2 = trackSyncBlocks(function (node) {
152
164
  return node.type.name === 'syncBlock';
153
165
  }, tr, state),
154
166
  syncBlockRemoved = _trackSyncBlocks2.removed,
155
167
  syncBlockAdded = _trackSyncBlocks2.added;
156
168
  var errorFlag = false;
169
+
170
+ // Disable (bodied)syncBlock node deletion/creation/edition in offline mode and trigger an error flag instead
157
171
  if (isConfirmedSyncBlockDeletion || bodiedSyncBlockRemoved.length > 0 || syncBlockRemoved.length > 0) {
158
172
  errorFlag = FLAG_ID.CANNOT_DELETE_WHEN_OFFLINE;
159
173
  } else if (bodiedSyncBlockAdded.length > 0 || syncBlockAdded.length > 0) {
@@ -177,7 +191,7 @@ export var createPlugin = function createPlugin(options, pmPluginFactoryParams,
177
191
  return true;
178
192
  },
179
193
  // @ts-ignore - Workaround for help-center local consumption
180
- appendTransaction: function appendTransaction(trs, _oldState, newState) {
194
+ appendTransaction: function appendTransaction(trs, oldState, newState) {
181
195
  trs
182
196
  // @ts-ignore - Workaround for help-center local consumption
183
197
  .filter(function (tr) {
@@ -187,6 +201,41 @@ export var createPlugin = function createPlugin(options, pmPluginFactoryParams,
187
201
  .forEach(function (tr) {
188
202
  syncBlockStore === null || syncBlockStore === void 0 || syncBlockStore.sourceManager.rebaseTransaction(tr, newState);
189
203
  });
204
+ var _iterator = _createForOfIteratorHelper(trs),
205
+ _step;
206
+ try {
207
+ var _loop = function _loop() {
208
+ var tr = _step.value;
209
+ if (!tr.getMeta(pmHistoryPluginKey)) {
210
+ return 0; // continue
211
+ }
212
+ var _trackSyncBlocks3 = trackSyncBlocks(syncBlockStore.sourceManager.isSourceBlock, tr, oldState),
213
+ added = _trackSyncBlocks3.added;
214
+ if (added.length > 0) {
215
+ // Delete bodiedSyncBlock if it's originated from history, i.e. redo creation
216
+ // See filterTransaction above for more details
217
+ var _tr = newState.tr;
218
+ added.forEach(function (node) {
219
+ if (node.from !== undefined && node.to !== undefined) {
220
+ _tr.delete(node.from, node.to);
221
+ }
222
+ });
223
+ return {
224
+ v: _tr
225
+ };
226
+ }
227
+ },
228
+ _ret;
229
+ for (_iterator.s(); !(_step = _iterator.n()).done;) {
230
+ _ret = _loop();
231
+ if (_ret === 0) continue;
232
+ if (_ret) return _ret.v;
233
+ }
234
+ } catch (err) {
235
+ _iterator.e(err);
236
+ } finally {
237
+ _iterator.f();
238
+ }
190
239
  return null;
191
240
  }
192
241
  });
@@ -27,7 +27,7 @@ export var trackSyncBlocks = function trackSyncBlocks(predicate, tr, state) {
27
27
  step.getMap().forEach(function (oldStart, oldEnd) {
28
28
  if (oldStart !== oldEnd && !hasChange) {
29
29
  var deletedSlice = state.doc.slice(Math.max(0, oldStart), Math.min(state.doc.content.size, oldEnd));
30
- deletedSlice.content.forEach(function (node, _, index) {
30
+ deletedSlice.content.forEach(function (node) {
31
31
  if (hasChange) {
32
32
  return;
33
33
  }
@@ -58,13 +58,19 @@ export var trackSyncBlocks = function trackSyncBlocks(predicate, tr, state) {
58
58
  oldDoc.content.forEach(function (node) {
59
59
  if (predicate(node)) {
60
60
  var syncBlockAttr = node.attrs;
61
- syncBlockMapOld[syncBlockAttr.localId] = syncBlockAttr;
61
+ syncBlockMapOld[syncBlockAttr.localId] = {
62
+ attrs: syncBlockAttr
63
+ };
62
64
  }
63
65
  });
64
- newDoc.content.forEach(function (node) {
66
+ newDoc.content.forEach(function (node, offset) {
65
67
  if (predicate(node)) {
66
68
  var syncBlockAttr = node.attrs;
67
- syncBlockMapNew[syncBlockAttr.localId] = syncBlockAttr;
69
+ syncBlockMapNew[syncBlockAttr.localId] = {
70
+ attrs: syncBlockAttr,
71
+ from: offset,
72
+ to: offset + node.nodeSize
73
+ };
68
74
  }
69
75
  });
70
76
 
@@ -51,7 +51,8 @@ export var DeleteConfirmationModal = function DeleteConfirmationModal(_ref) {
51
51
  };
52
52
  }, [syncBlockStoreManager, confirmationCallback]);
53
53
  return /*#__PURE__*/React.createElement(ModalTransition, null, isOpen && /*#__PURE__*/React.createElement(ModalDialog, {
54
- onClose: handleClose(false)
54
+ onClose: handleClose(false),
55
+ testId: "sync-block-delete-confirmation"
55
56
  }, /*#__PURE__*/React.createElement(ModalHeader, {
56
57
  hasCloseButton: true
57
58
  }, /*#__PURE__*/React.createElement(ModalTitle, {
@@ -2,8 +2,16 @@ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
2
2
  import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
3
3
  import type { SyncBlockAttrs } from '../../syncedBlockPluginType';
4
4
  export declare const trackSyncBlocks: (predicate: (node: PMNode) => boolean, tr: Transaction, state: EditorState) => {
5
- removed: SyncBlockAttrs[];
6
- added: SyncBlockAttrs[];
5
+ removed: {
6
+ attrs: SyncBlockAttrs;
7
+ from?: number;
8
+ to?: number;
9
+ }[];
10
+ added: {
11
+ attrs: SyncBlockAttrs;
12
+ from?: number;
13
+ to?: number;
14
+ }[];
7
15
  };
8
16
  /**
9
17
  *
@@ -2,8 +2,16 @@ import type { Node as PMNode } from '@atlaskit/editor-prosemirror/model';
2
2
  import type { EditorState, Transaction } from '@atlaskit/editor-prosemirror/state';
3
3
  import type { SyncBlockAttrs } from '../../syncedBlockPluginType';
4
4
  export declare const trackSyncBlocks: (predicate: (node: PMNode) => boolean, tr: Transaction, state: EditorState) => {
5
- removed: SyncBlockAttrs[];
6
- added: SyncBlockAttrs[];
5
+ removed: {
6
+ attrs: SyncBlockAttrs;
7
+ from?: number;
8
+ to?: number;
9
+ }[];
10
+ added: {
11
+ attrs: SyncBlockAttrs;
12
+ from?: number;
13
+ to?: number;
14
+ }[];
7
15
  };
8
16
  /**
9
17
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlaskit/editor-plugin-synced-block",
3
- "version": "4.3.9",
3
+ "version": "4.3.10",
4
4
  "description": "SyncedBlock plugin for @atlaskit/editor-core",
5
5
  "author": "Atlassian Pty Ltd",
6
6
  "license": "Apache-2.0",