@atlaskit/editor-plugin-synced-block 4.3.8 → 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 +14 -0
- package/dist/cjs/pm-plugins/main.js +56 -7
- package/dist/cjs/pm-plugins/utils/track-sync-blocks.js +10 -4
- package/dist/cjs/ui/DeleteConfirmationModal.js +2 -1
- package/dist/es2019/pm-plugins/main.js +31 -3
- package/dist/es2019/pm-plugins/utils/track-sync-blocks.js +10 -4
- package/dist/es2019/ui/DeleteConfirmationModal.js +2 -1
- package/dist/esm/pm-plugins/main.js +52 -3
- package/dist/esm/pm-plugins/utils/track-sync-blocks.js +10 -4
- package/dist/esm/ui/DeleteConfirmationModal.js +2 -1
- package/dist/types/pm-plugins/utils/track-sync-blocks.d.ts +10 -2
- package/dist/types-ts4.5/pm-plugins/utils/track-sync-blocks.d.ts +10 -2
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
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
|
+
|
|
11
|
+
## 4.3.9
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- Updated dependencies
|
|
16
|
+
|
|
3
17
|
## 4.3.8
|
|
4
18
|
|
|
5
19
|
### 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
|
|
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,
|
|
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
|
-
|
|
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,
|
|
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,
|
|
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
|
|
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] =
|
|
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] =
|
|
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,
|
|
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(
|
|
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] =
|
|
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] =
|
|
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,
|
|
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
|
|
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] =
|
|
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] =
|
|
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:
|
|
6
|
-
|
|
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:
|
|
6
|
-
|
|
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.
|
|
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",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@atlaskit/editor-shared-styles": "^3.10.0",
|
|
42
42
|
"@atlaskit/editor-synced-block-provider": "^2.11.0",
|
|
43
43
|
"@atlaskit/editor-tables": "^2.9.0",
|
|
44
|
-
"@atlaskit/editor-toolbar": "^0.
|
|
44
|
+
"@atlaskit/editor-toolbar": "^0.18.0",
|
|
45
45
|
"@atlaskit/flag": "^17.5.0",
|
|
46
46
|
"@atlaskit/icon": "29.0.0",
|
|
47
47
|
"@atlaskit/icon-lab": "^5.12.0",
|