@atlaskit/editor-plugin-block-controls 11.2.9 → 11.2.11
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/editor-commands/move-node.js +12 -32
- package/dist/cjs/editor-commands/move-to-layout.js +59 -127
- package/dist/cjs/pm-plugins/decorations-drop-target-active.js +11 -16
- package/dist/cjs/pm-plugins/decorations-drop-target.js +13 -24
- package/dist/cjs/pm-plugins/main.js +51 -88
- package/dist/cjs/pm-plugins/utils/analytics.js +1 -2
- package/dist/cjs/pm-plugins/utils/remove-from-source.js +4 -14
- package/dist/cjs/ui/drag-handle.js +32 -44
- package/dist/es2019/editor-commands/move-node.js +9 -31
- package/dist/es2019/editor-commands/move-to-layout.js +61 -121
- package/dist/es2019/pm-plugins/decorations-drop-target-active.js +11 -16
- package/dist/es2019/pm-plugins/decorations-drop-target.js +13 -24
- package/dist/es2019/pm-plugins/main.js +55 -91
- package/dist/es2019/pm-plugins/utils/analytics.js +1 -2
- package/dist/es2019/pm-plugins/utils/remove-from-source.js +4 -14
- package/dist/es2019/ui/drag-handle.js +32 -45
- package/dist/esm/editor-commands/move-node.js +13 -33
- package/dist/esm/editor-commands/move-to-layout.js +59 -127
- package/dist/esm/pm-plugins/decorations-drop-target-active.js +11 -16
- package/dist/esm/pm-plugins/decorations-drop-target.js +13 -24
- package/dist/esm/pm-plugins/main.js +51 -88
- package/dist/esm/pm-plugins/utils/analytics.js +1 -2
- package/dist/esm/pm-plugins/utils/remove-from-source.js +4 -14
- package/dist/esm/ui/drag-handle.js +32 -44
- package/dist/types/pm-plugins/main.d.ts +0 -1
- package/dist/types/pm-plugins/utils/analytics.d.ts +2 -2
- package/dist/types/pm-plugins/utils/remove-from-source.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/main.d.ts +0 -1
- package/dist/types-ts4.5/pm-plugins/utils/analytics.d.ts +2 -2
- package/dist/types-ts4.5/pm-plugins/utils/remove-from-source.d.ts +1 -1
- package/editor-plugin-block-controls.docs.tsx +38 -0
- package/package.json +4 -3
|
@@ -41,26 +41,13 @@ const createNewLayout = (schema, layoutContents) => {
|
|
|
41
41
|
};
|
|
42
42
|
const moveToExistingLayout = (toLayout, toLayoutPos, sourceContent, from, to, tr, $originalFrom, $originalTo, api, selectMovedNode) => {
|
|
43
43
|
const isSameLayout = isInSameLayout($originalFrom, $originalTo);
|
|
44
|
-
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const attributes = getMultiSelectAnalyticsAttributes(tr, from, sourceContentEndPos);
|
|
51
|
-
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
52
|
-
sourceNodeTypes = attributes.nodeTypes;
|
|
53
|
-
}
|
|
54
|
-
} else {
|
|
55
|
-
if (sourceContent instanceof PMNode) {
|
|
56
|
-
sourceContentEndPos = from + sourceContent.nodeSize;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
if (sourceContentEndPos === -1) {
|
|
60
|
-
return tr;
|
|
61
|
-
}
|
|
44
|
+
const sourceContentEndPos = from + sourceContent.size;
|
|
45
|
+
const attributes = getMultiSelectAnalyticsAttributes(tr, from, sourceContentEndPos);
|
|
46
|
+
const {
|
|
47
|
+
nodeTypes: sourceNodeTypes,
|
|
48
|
+
hasSelectedMultipleNodes
|
|
49
|
+
} = attributes;
|
|
62
50
|
if (isSameLayout) {
|
|
63
|
-
var _$originalFrom$nodeAf;
|
|
64
51
|
// reorder columns
|
|
65
52
|
tr.delete(from, sourceContentEndPos);
|
|
66
53
|
const mappedTo = tr.mapping.map(to);
|
|
@@ -68,12 +55,11 @@ const moveToExistingLayout = (toLayout, toLayoutPos, sourceContent, from, to, tr
|
|
|
68
55
|
if (selectMovedNode) {
|
|
69
56
|
tr.setSelection(new NodeSelection(tr.doc.resolve(mappedTo))).scrollIntoView();
|
|
70
57
|
}
|
|
71
|
-
attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth,
|
|
58
|
+
attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth, sourceNodeTypes, 1, 'layoutSection', true, api, hasSelectedMultipleNodes);
|
|
72
59
|
} else if (toLayout.childCount < maxLayoutColumnSupported()) {
|
|
73
|
-
var _$originalFrom$nodeAf2;
|
|
74
60
|
removeFromSource(tr, tr.doc.resolve(from), sourceContentEndPos);
|
|
75
61
|
insertToDestinationNoWidthUpdate(tr, tr.mapping.map(to), sourceContent);
|
|
76
|
-
attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth,
|
|
62
|
+
attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth, sourceNodeTypes, 1, 'layoutSection', false, api, hasSelectedMultipleNodes);
|
|
77
63
|
}
|
|
78
64
|
return tr;
|
|
79
65
|
};
|
|
@@ -92,22 +78,11 @@ const insertToDestinationNoWidthUpdate = (tr, to, sourceContent) => {
|
|
|
92
78
|
} = tr.doc.type.schema.nodes || {};
|
|
93
79
|
let content = null;
|
|
94
80
|
try {
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
width: 0
|
|
101
|
-
}, isFragmentOfType(sourceFragment, 'layoutColumn') ? (_sourceFragment$first = sourceFragment.firstChild) === null || _sourceFragment$first === void 0 ? void 0 : _sourceFragment$first.content : sourceFragment);
|
|
102
|
-
}
|
|
103
|
-
} else {
|
|
104
|
-
if (sourceContent instanceof PMNode) {
|
|
105
|
-
const sourceNode = sourceContent;
|
|
106
|
-
content = layoutColumn.createChecked({
|
|
107
|
-
width: 0
|
|
108
|
-
}, sourceNode.type.name === 'layoutColumn' ? sourceNode.content : sourceNode);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
81
|
+
var _sourceFragment$first;
|
|
82
|
+
const sourceFragment = sourceContent;
|
|
83
|
+
content = layoutColumn.createChecked({
|
|
84
|
+
width: 0
|
|
85
|
+
}, isFragmentOfType(sourceFragment, 'layoutColumn') ? (_sourceFragment$first = sourceFragment.firstChild) === null || _sourceFragment$first === void 0 ? void 0 : _sourceFragment$first.content : sourceFragment);
|
|
111
86
|
} catch (error) {
|
|
112
87
|
logException(error, {
|
|
113
88
|
location: 'editor-plugin-block-controls/move-to-layout'
|
|
@@ -151,7 +126,6 @@ const canMoveToLayout = (api, from, to, tr, moveNodeAtCursorPos) => {
|
|
|
151
126
|
return;
|
|
152
127
|
}
|
|
153
128
|
const $from = tr.doc.resolve(from);
|
|
154
|
-
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
|
|
155
129
|
|
|
156
130
|
// invalid from position or dragging a layout
|
|
157
131
|
if (!$from.nodeAfter || $from.nodeAfter.type === layoutSection) {
|
|
@@ -160,7 +134,7 @@ const canMoveToLayout = (api, from, to, tr, moveNodeAtCursorPos) => {
|
|
|
160
134
|
let sourceContent = $from.nodeAfter;
|
|
161
135
|
let sourceFrom = from;
|
|
162
136
|
let sourceTo = from + sourceContent.nodeSize;
|
|
163
|
-
if (
|
|
137
|
+
if (!moveNodeAtCursorPos) {
|
|
164
138
|
const {
|
|
165
139
|
anchor,
|
|
166
140
|
head
|
|
@@ -188,62 +162,46 @@ const canMoveToLayout = (api, from, to, tr, moveNodeAtCursorPos) => {
|
|
|
188
162
|
};
|
|
189
163
|
};
|
|
190
164
|
const removeBreakoutMarks = (tr, $from, to) => {
|
|
191
|
-
let fromContentWithoutBreakout =
|
|
165
|
+
let fromContentWithoutBreakout = null;
|
|
192
166
|
const {
|
|
193
167
|
breakout
|
|
194
168
|
} = tr.doc.type.schema.marks || {};
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (
|
|
199
|
-
|
|
200
|
-
return false;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// breakout doesn't exist on nested nodes
|
|
205
|
-
if ((parent === null || parent === void 0 ? void 0 : parent.type.name) === 'doc' && node.marks.some(m => m.type === breakout)) {
|
|
206
|
-
tr.removeNodeMark(pos, breakout);
|
|
169
|
+
tr.doc.nodesBetween($from.pos, to, (node, pos, parent) => {
|
|
170
|
+
// should never remove breakout from previous layoutSection
|
|
171
|
+
if (expValEquals('platform_editor_breakout_resizing', 'isEnabled', true)) {
|
|
172
|
+
if (node.type.name === 'layoutSection') {
|
|
173
|
+
return false;
|
|
207
174
|
}
|
|
175
|
+
}
|
|
208
176
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
// resolve again the source content after node updated (remove breakout marks)
|
|
213
|
-
fromContentWithoutBreakout = tr.doc.slice($from.pos, to).content;
|
|
214
|
-
} else {
|
|
215
|
-
if (breakout && $from.nodeAfter && $from.nodeAfter.marks.some(m => m.type === breakout)) {
|
|
216
|
-
tr.removeNodeMark($from.pos, breakout);
|
|
217
|
-
// resolve again the source node after node updated (remove breakout marks)
|
|
218
|
-
fromContentWithoutBreakout = tr.doc.resolve($from.pos).nodeAfter;
|
|
177
|
+
// breakout doesn't exist on nested nodes
|
|
178
|
+
if ((parent === null || parent === void 0 ? void 0 : parent.type.name) === 'doc' && node.marks.some(m => m.type === breakout)) {
|
|
179
|
+
tr.removeNodeMark(pos, breakout);
|
|
219
180
|
}
|
|
220
|
-
|
|
181
|
+
|
|
182
|
+
// descending is not needed as breakout doesn't exist on nested nodes
|
|
183
|
+
return false;
|
|
184
|
+
});
|
|
185
|
+
// resolve again the source content after node updated (remove breakout marks)
|
|
186
|
+
fromContentWithoutBreakout = tr.doc.slice($from.pos, to).content;
|
|
221
187
|
return fromContentWithoutBreakout;
|
|
222
188
|
};
|
|
223
189
|
const getBreakoutMode = (content, breakout) => {
|
|
224
|
-
if (
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
break;
|
|
237
|
-
}
|
|
190
|
+
if (content instanceof PMNode) {
|
|
191
|
+
var _content$marks$find;
|
|
192
|
+
return (_content$marks$find = content.marks.find(m => m.type === breakout)) === null || _content$marks$find === void 0 ? void 0 : _content$marks$find.attrs.mode;
|
|
193
|
+
} else if (content instanceof Fragment) {
|
|
194
|
+
// Find the first breakout mode in the fragment
|
|
195
|
+
let firstBreakoutMode;
|
|
196
|
+
for (let i = 0; i < content.childCount; i++) {
|
|
197
|
+
const child = content.child(i);
|
|
198
|
+
const breakoutMark = child.marks.find(m => m.type === breakout);
|
|
199
|
+
if (breakoutMark) {
|
|
200
|
+
firstBreakoutMode = breakoutMark.attrs.mode;
|
|
201
|
+
break;
|
|
238
202
|
}
|
|
239
|
-
return firstBreakoutMode;
|
|
240
|
-
}
|
|
241
|
-
} else {
|
|
242
|
-
// Without multi-select support, we can assume source content is of type PMNode
|
|
243
|
-
if (content instanceof PMNode) {
|
|
244
|
-
var _content$marks$find2;
|
|
245
|
-
return (_content$marks$find2 = content.marks.find(m => m.type === breakout)) === null || _content$marks$find2 === void 0 ? void 0 : _content$marks$find2.attrs.mode;
|
|
246
203
|
}
|
|
204
|
+
return firstBreakoutMode;
|
|
247
205
|
}
|
|
248
206
|
};
|
|
249
207
|
const getBreakoutModeAndWidth = (content, breakout) => {
|
|
@@ -252,30 +210,20 @@ const getBreakoutModeAndWidth = (content, breakout) => {
|
|
|
252
210
|
breakoutMode: mark.attrs.mode,
|
|
253
211
|
breakoutWidth: mark.attrs.width
|
|
254
212
|
} : null;
|
|
255
|
-
if (
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
return extractBreakoutAttributes(breakoutMark);
|
|
265
|
-
}
|
|
213
|
+
if (content instanceof PMNode) {
|
|
214
|
+
return extractBreakoutAttributes(findBreakoutMark(content));
|
|
215
|
+
} else if (content instanceof Fragment) {
|
|
216
|
+
// Find the first breakout mode in the fragment
|
|
217
|
+
for (let i = 0; i < content.childCount; i++) {
|
|
218
|
+
const child = content.child(i);
|
|
219
|
+
const breakoutMark = findBreakoutMark(child);
|
|
220
|
+
if (breakoutMark) {
|
|
221
|
+
return extractBreakoutAttributes(breakoutMark);
|
|
266
222
|
}
|
|
267
223
|
}
|
|
268
|
-
} else {
|
|
269
|
-
// Without multi-select support, we can assume source content is of type PMNode
|
|
270
|
-
if (content instanceof PMNode) {
|
|
271
|
-
return extractBreakoutAttributes(findBreakoutMark(content));
|
|
272
|
-
}
|
|
273
224
|
}
|
|
274
225
|
return null;
|
|
275
226
|
};
|
|
276
|
-
|
|
277
|
-
// TODO: ED-26959 - As part of platform_editor_element_drag_and_drop_multiselect clean up,
|
|
278
|
-
// source content variable that has type of `PMNode | Fragment` should be updated to `Fragment` only
|
|
279
227
|
export const moveToLayout = api => (from, to, options) => ({
|
|
280
228
|
tr
|
|
281
229
|
}) => {
|
|
@@ -315,8 +263,8 @@ export const moveToLayout = api => (from, to, options) => ({
|
|
|
315
263
|
}
|
|
316
264
|
|
|
317
265
|
// we don't want to remove marks when moving/re-ordering layoutSection
|
|
318
|
-
const shouldRemoveMarks =
|
|
319
|
-
const fromContentBeforeBreakoutMarksRemoved =
|
|
266
|
+
const shouldRemoveMarks = $sourceFrom.node().type !== layoutSection;
|
|
267
|
+
const fromContentBeforeBreakoutMarksRemoved = tr.doc.slice($sourceFrom.pos, sourceTo).content;
|
|
320
268
|
|
|
321
269
|
// remove breakout from source content
|
|
322
270
|
let fromContentWithoutBreakout = shouldRemoveMarks ? removeBreakoutMarks(tr, $sourceFrom, sourceTo) : fromContentBeforeBreakoutMarksRemoved;
|
|
@@ -329,7 +277,6 @@ export const moveToLayout = api => (from, to, options) => ({
|
|
|
329
277
|
tr
|
|
330
278
|
});
|
|
331
279
|
}
|
|
332
|
-
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
|
|
333
280
|
if (toNode.type === layoutSection) {
|
|
334
281
|
const toPos = options !== null && options !== void 0 && options.moveToEnd ? to + toNode.nodeSize - 1 : to + 1;
|
|
335
282
|
return moveToExistingLayout(toNode, to, fromContentWithoutBreakout, $sourceFrom.pos, toPos, tr, $sourceFrom, $to, api, options === null || options === void 0 ? void 0 : options.selectMovedNode);
|
|
@@ -347,24 +294,17 @@ export const moveToLayout = api => (from, to, options) => ({
|
|
|
347
294
|
// resolve again the source node after node updated (remove breakout marks)
|
|
348
295
|
toNodeWithoutBreakout = tr.doc.resolve(to).nodeAfter || toNode;
|
|
349
296
|
}
|
|
350
|
-
if (
|
|
351
|
-
|
|
352
|
-
fromContentWithoutBreakout = fromContentWithoutBreakout.firstChild.content;
|
|
353
|
-
}
|
|
354
|
-
} else {
|
|
355
|
-
if (fromContentWithoutBreakout instanceof PMNode && fromContentWithoutBreakout.type.name === 'layoutColumn') {
|
|
356
|
-
fromContentWithoutBreakout = fromContentWithoutBreakout.content;
|
|
357
|
-
}
|
|
297
|
+
if (isFragmentOfType(fromContentWithoutBreakout, 'layoutColumn') && fromContentWithoutBreakout.firstChild) {
|
|
298
|
+
fromContentWithoutBreakout = fromContentWithoutBreakout.firstChild.content;
|
|
358
299
|
}
|
|
359
300
|
const layoutContents = options !== null && options !== void 0 && options.moveToEnd ? [toNodeWithoutBreakout, fromContentWithoutBreakout] : [fromContentWithoutBreakout, toNodeWithoutBreakout];
|
|
360
301
|
const newLayout = createNewLayout(tr.doc.type.schema, layoutContents);
|
|
361
302
|
if (newLayout) {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
hasSelectedMultipleNodes
|
|
366
|
-
|
|
367
|
-
}
|
|
303
|
+
const attributes = getMultiSelectAnalyticsAttributes(tr, $sourceFrom.pos, sourceTo);
|
|
304
|
+
const {
|
|
305
|
+
nodeTypes: sourceNodeTypes,
|
|
306
|
+
hasSelectedMultipleNodes
|
|
307
|
+
} = attributes;
|
|
368
308
|
tr = removeFromSource(tr, $sourceFrom, sourceTo);
|
|
369
309
|
const mappedTo = tr.mapping.map(to);
|
|
370
310
|
tr.delete(mappedTo, mappedTo + toNodeWithoutBreakout.nodeSize).insert(mappedTo, newLayout);
|
|
@@ -40,24 +40,19 @@ export const canMoveNodeOrSliceToPos = (state, node, parent, index, $toPos, acti
|
|
|
40
40
|
const $activeNodePos = typeof activeNodePos === 'number' && state.doc.resolve(activeNodePos);
|
|
41
41
|
const activePMNode = $activeNodePos && $activeNodePos.nodeAfter;
|
|
42
42
|
const handleInsideSelection = activeNodePos !== undefined && activeNodePos >= selectionFrom && activeNodePos <= selectionTo;
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
let canDropMultipleNodes = true;
|
|
43
|
+
const selectionSlice = state.doc.slice(selectionFrom, selectionTo, false);
|
|
44
|
+
const selectionSliceChildCount = selectionSlice.content.childCount;
|
|
45
|
+
let canDropSingleNode = true;
|
|
46
|
+
let canDropMultipleNodes = true;
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
} else {
|
|
53
|
-
canDropSingleNode = !!(activePMNode && canMoveNodeToIndex(parent, index, activePMNode, $toPos, node));
|
|
54
|
-
}
|
|
55
|
-
if (!canDropMultipleNodes || !canDropSingleNode) {
|
|
56
|
-
return false;
|
|
57
|
-
}
|
|
48
|
+
// when there is only one node in the slice, use the same logic as when multi select is not on
|
|
49
|
+
if (selectionSliceChildCount > 1 && handleInsideSelection) {
|
|
50
|
+
canDropMultipleNodes = canMoveSliceToIndex(selectionSlice, selectionFrom, selectionTo, parent, index, $toPos);
|
|
58
51
|
} else {
|
|
59
|
-
|
|
60
|
-
|
|
52
|
+
canDropSingleNode = !!(activePMNode && canMoveNodeToIndex(parent, index, activePMNode, $toPos, node));
|
|
53
|
+
}
|
|
54
|
+
if (!canDropMultipleNodes || !canDropSingleNode) {
|
|
55
|
+
return false;
|
|
61
56
|
}
|
|
62
57
|
return true;
|
|
63
58
|
};
|
|
@@ -161,7 +161,6 @@ export const dropTargetDecorations = (newState, api, formatMessage, nodeViewPort
|
|
|
161
161
|
const activeNodePos = activeNode === null || activeNode === void 0 ? void 0 : activeNode.pos;
|
|
162
162
|
const $activeNodePos = typeof activeNodePos === 'number' && newState.doc.resolve(activeNodePos);
|
|
163
163
|
const activePMNode = $activeNodePos && $activeNodePos.nodeAfter;
|
|
164
|
-
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
|
|
165
164
|
anchorRectCache === null || anchorRectCache === void 0 ? void 0 : anchorRectCache.clear();
|
|
166
165
|
const prevNodeStack = [];
|
|
167
166
|
const popNodeStack = depth => {
|
|
@@ -218,31 +217,21 @@ export const dropTargetDecorations = (newState, api, formatMessage, nodeViewPort
|
|
|
218
217
|
return shouldDescend(node); //skip over, don't consider it a valid depth
|
|
219
218
|
}
|
|
220
219
|
|
|
221
|
-
//
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
let canDropMultipleNodes = true;
|
|
220
|
+
// validate all the nodes in the selection instead of just the handle node
|
|
221
|
+
const selectionSlice = newState.doc.slice(selectionFrom, selectionTo, false);
|
|
222
|
+
const selectionSliceChildCount = selectionSlice.content.childCount;
|
|
223
|
+
let canDropSingleNode = true;
|
|
224
|
+
let canDropMultipleNodes = true;
|
|
227
225
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
} else {
|
|
232
|
-
canDropSingleNode = !!(activePMNode && canMoveNodeToIndex(parent, index, activePMNode, $pos, node));
|
|
233
|
-
}
|
|
234
|
-
if (!canDropMultipleNodes || !canDropSingleNode) {
|
|
235
|
-
pushNodeStack(node, depth);
|
|
236
|
-
return false; //not valid pos, so nested not valid either
|
|
237
|
-
}
|
|
226
|
+
// when there is only one node in the slice, use the same logic as when multi select is not on
|
|
227
|
+
if (selectionSliceChildCount > 1 && handleInsideSelection) {
|
|
228
|
+
canDropMultipleNodes = canMoveSliceToIndex(selectionSlice, selectionFrom, selectionTo, parent, index, $pos);
|
|
238
229
|
} else {
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
return false; //not valid pos, so nested not valid either
|
|
245
|
-
}
|
|
230
|
+
canDropSingleNode = !!(activePMNode && canMoveNodeToIndex(parent, index, activePMNode, $pos, node));
|
|
231
|
+
}
|
|
232
|
+
if (!canDropMultipleNodes || !canDropSingleNode) {
|
|
233
|
+
pushNodeStack(node, depth);
|
|
234
|
+
return false; //not valid pos, so nested not valid either
|
|
246
235
|
}
|
|
247
236
|
const parentTypesWithEndDropTarget = editorExperiment('platform_synced_block', true) ? PARENT_WITH_END_DROP_TARGET_NEXT : PARENT_WITH_END_DROP_TARGET;
|
|
248
237
|
if (parent.lastChild === node && !isEmptyParagraph(node) && parentTypesWithEndDropTarget.includes(parent.type.name)) {
|
|
@@ -105,32 +105,28 @@ const destroyFn = (api, editorView) => {
|
|
|
105
105
|
(_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
|
|
106
106
|
tr
|
|
107
107
|
}) => {
|
|
108
|
-
var _api$userIntent;
|
|
109
|
-
const
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
if (
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
if (
|
|
120
|
-
const $
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
selectNode(tr, $from.pos, $from.node().type.name, api);
|
|
125
|
-
} else {
|
|
126
|
-
tr.setSelection(TextSelection.create(tr.doc, multiSelectDnD.userAnchor, multiSelectDnD.userHead));
|
|
127
|
-
}
|
|
108
|
+
var _api$blockControls, _api$selection, _api$userIntent;
|
|
109
|
+
const {
|
|
110
|
+
multiSelectDnD
|
|
111
|
+
} = ((_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {};
|
|
112
|
+
// Restore the users initial Editor selection when the drop completes
|
|
113
|
+
if (multiSelectDnD) {
|
|
114
|
+
// If the TextSelection between the drag start and end has changed, the document has changed, and we should not reapply the last selection
|
|
115
|
+
const expandedSelectionUnchanged = multiSelectDnD.textAnchor === tr.selection.anchor && multiSelectDnD.textHead === tr.selection.head;
|
|
116
|
+
if (expandedSelectionUnchanged) {
|
|
117
|
+
const $anchor = tr.doc.resolve(multiSelectDnD.userAnchor);
|
|
118
|
+
const $head = tr.doc.resolve(multiSelectDnD.userHead);
|
|
119
|
+
if ($head.node() === $anchor.node()) {
|
|
120
|
+
const $from = $anchor.min($head);
|
|
121
|
+
selectNode(tr, $from.pos, $from.node().type.name, api);
|
|
122
|
+
} else {
|
|
123
|
+
tr.setSelection(TextSelection.create(tr.doc, multiSelectDnD.userAnchor, multiSelectDnD.userHead));
|
|
128
124
|
}
|
|
129
125
|
}
|
|
130
|
-
(_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : _api$selection.commands.clearManualSelection()({
|
|
131
|
-
tr
|
|
132
|
-
});
|
|
133
126
|
}
|
|
127
|
+
(_api$selection = api.selection) === null || _api$selection === void 0 ? void 0 : _api$selection.commands.clearManualSelection()({
|
|
128
|
+
tr
|
|
129
|
+
});
|
|
134
130
|
const {
|
|
135
131
|
start
|
|
136
132
|
} = source.data;
|
|
@@ -138,15 +134,13 @@ const destroyFn = (api, editorView) => {
|
|
|
138
134
|
const lastDragCancelled = location.current.dropTargets.length === 0;
|
|
139
135
|
if (lastDragCancelled) {
|
|
140
136
|
var _api$analytics2;
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
}
|
|
137
|
+
const position = getSelectedSlicePosition(start, tr, api);
|
|
138
|
+
const attributes = getMultiSelectAnalyticsAttributes(tr, position.from, position.to);
|
|
139
|
+
const {
|
|
140
|
+
nodeTypes,
|
|
141
|
+
hasSelectedMultipleNodes
|
|
142
|
+
} = attributes;
|
|
148
143
|
const resolvedMovingNode = tr.doc.resolve(start);
|
|
149
|
-
const maybeNode = resolvedMovingNode.nodeAfter;
|
|
150
144
|
(_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.attachAnalyticsEvent({
|
|
151
145
|
eventType: EVENT_TYPE.UI,
|
|
152
146
|
action: ACTION.CANCELLED,
|
|
@@ -154,11 +148,8 @@ const destroyFn = (api, editorView) => {
|
|
|
154
148
|
actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
|
|
155
149
|
attributes: {
|
|
156
150
|
nodeDepth: resolvedMovingNode.depth,
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
nodeTypes,
|
|
160
|
-
hasSelectedMultipleNodes
|
|
161
|
-
})
|
|
151
|
+
nodeTypes: nodeTypes || '',
|
|
152
|
+
hasSelectedMultipleNodes
|
|
162
153
|
}
|
|
163
154
|
})(tr);
|
|
164
155
|
}
|
|
@@ -328,7 +319,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
328
319
|
};
|
|
329
320
|
}
|
|
330
321
|
}
|
|
331
|
-
if (multiSelectDnD
|
|
322
|
+
if (multiSelectDnD) {
|
|
332
323
|
multiSelectDnD.anchor = tr.mapping.map(multiSelectDnD.anchor);
|
|
333
324
|
multiSelectDnD.head = tr.mapping.map(multiSelectDnD.head);
|
|
334
325
|
}
|
|
@@ -337,7 +328,7 @@ export const apply = (api, formatMessage, tr, currentState, newState, flags, nod
|
|
|
337
328
|
isResizerResizing = resizerMeta !== null && resizerMeta !== void 0 ? resizerMeta : isResizerResizing;
|
|
338
329
|
const hasJustFinishedResizing = resizerMeta === false;
|
|
339
330
|
multiSelectDnD = (_meta$multiSelectDnD = meta === null || meta === void 0 ? void 0 : meta.multiSelectDnD) !== null && _meta$multiSelectDnD !== void 0 ? _meta$multiSelectDnD : multiSelectDnD;
|
|
340
|
-
if (multiSelectDnD
|
|
331
|
+
if (multiSelectDnD) {
|
|
341
332
|
var _meta$isDragging;
|
|
342
333
|
if (((_meta$isDragging = meta === null || meta === void 0 ? void 0 : meta.isDragging) !== null && _meta$isDragging !== void 0 ? _meta$isDragging : isDragging) && expValEquals('platform_editor_block_controls_perf_optimization', 'isEnabled', true)) {
|
|
343
334
|
// When dragging, we want to keep the multiSelectDnD object unless both document and selection
|
|
@@ -694,12 +685,8 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
694
685
|
const isAdvancedLayoutEnabled = editorExperiment('advanced_layouts', true, {
|
|
695
686
|
exposure: true
|
|
696
687
|
});
|
|
697
|
-
const isMultiSelectEnabled = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
|
|
698
|
-
exposure: true
|
|
699
|
-
});
|
|
700
688
|
const toolbarFlagsEnabled = areToolbarFlagsEnabled(Boolean(api === null || api === void 0 ? void 0 : api.toolbar));
|
|
701
689
|
const flags = {
|
|
702
|
-
isMultiSelectEnabled,
|
|
703
690
|
toolbarFlagsEnabled
|
|
704
691
|
};
|
|
705
692
|
let anchorRectCache;
|
|
@@ -754,7 +741,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
754
741
|
const tr = state.tr;
|
|
755
742
|
let pluginState = key.getState(state);
|
|
756
743
|
const dndDragCancelled = (_pluginState = pluginState) === null || _pluginState === void 0 ? void 0 : _pluginState.lastDragCancelled;
|
|
757
|
-
if ((_pluginState2 = pluginState) !== null && _pluginState2 !== void 0 && _pluginState2.isPMDragging || dndDragCancelled
|
|
744
|
+
if ((_pluginState2 = pluginState) !== null && _pluginState2 !== void 0 && _pluginState2.isPMDragging || dndDragCancelled) {
|
|
758
745
|
if (fg('platform_editor_ease_of_use_metrics')) {
|
|
759
746
|
var _api$metrics2;
|
|
760
747
|
api === null || api === void 0 ? void 0 : (_api$metrics2 = api.metrics) === null || _api$metrics2 === void 0 ? void 0 : _api$metrics2.commands.startActiveSessionTimer()({
|
|
@@ -774,7 +761,7 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
774
761
|
// Currently we can only drag one node at a time
|
|
775
762
|
// so we only need to check first child
|
|
776
763
|
const draggable = dragging === null || dragging === void 0 ? void 0 : dragging.slice.content.firstChild;
|
|
777
|
-
if (dndDragCancelled
|
|
764
|
+
if (dndDragCancelled || (draggable === null || draggable === void 0 ? void 0 : draggable.type.name) === 'layoutColumn') {
|
|
778
765
|
// we prevent native DnD for layoutColumn to prevent single column layout.
|
|
779
766
|
event.preventDefault();
|
|
780
767
|
return false;
|
|
@@ -905,56 +892,33 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI, nodeDecora
|
|
|
905
892
|
if (api !== null && api !== void 0 && (_api$limitedMode8 = api.limitedMode) !== null && _api$limitedMode8 !== void 0 && (_api$limitedMode8$sha = _api$limitedMode8.sharedState.currentState()) !== null && _api$limitedMode8$sha !== void 0 && _api$limitedMode8$sha.enabled) {
|
|
906
893
|
return;
|
|
907
894
|
}
|
|
908
|
-
if (
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
return true;
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
if ((event.key === 'Enter' || event.key === ' ') && event.target instanceof HTMLElement && editorExperiment('platform_editor_controls', 'variant1')) {
|
|
917
|
-
const isDragHandle = event.target.closest(editorExperiment('platform_editor_block_menu', true) ? DRAG_HANDLE_SELECTOR : '[data-editor-block-ctrl-drag-handle="true"]') !== null;
|
|
918
|
-
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(isDragHandle));
|
|
895
|
+
if (event.shiftKey && event.ctrlKey) {
|
|
896
|
+
//prevent holding down key combo from firing repeatedly
|
|
897
|
+
if (!event.repeat && boundKeydownHandler(api, formatMessage)(view, event)) {
|
|
898
|
+
event.preventDefault();
|
|
899
|
+
return true;
|
|
919
900
|
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
isShiftDown: true
|
|
933
|
-
}));
|
|
934
|
-
}
|
|
935
|
-
return false;
|
|
936
|
-
} else {
|
|
937
|
-
if (event.shiftKey && event.ctrlKey) {
|
|
938
|
-
//prevent holding down key combo from firing repeatedly
|
|
939
|
-
if (!event.repeat && boundKeydownHandler(api, formatMessage)(view, event)) {
|
|
940
|
-
event.preventDefault();
|
|
941
|
-
return true;
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
if ((event.key === 'Enter' || event.key === ' ') && event.target instanceof HTMLElement && editorExperiment('platform_editor_controls', 'variant1')) {
|
|
945
|
-
const isDragHandle = event.target.closest(editorExperiment('platform_editor_block_menu', true) ? DRAG_HANDLE_SELECTOR : '[data-editor-block-ctrl-drag-handle="true"]') !== null;
|
|
946
|
-
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(isDragHandle));
|
|
947
|
-
}
|
|
948
|
-
if ((event.key === 'ArrowLeft' || event.key === 'ArrowRight' || event.key === 'ArrowDown' || event.key === 'ArrowUp') && editorExperiment('platform_editor_controls', 'variant1')) {
|
|
949
|
-
var _api$blockControls$sh4, _api$blockControls$sh5;
|
|
950
|
-
const isBlockMenuOpen = (api === null || api === void 0 ? void 0 : (_api$blockControls$sh4 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh4 === void 0 ? void 0 : _api$blockControls$sh4.isMenuOpen) && editorExperiment('platform_editor_block_menu', true);
|
|
951
|
-
// when block menu is just open, and we press arrow keys, we want to use the arrow keys to navigate the block menu
|
|
952
|
-
// in this scenario, isSelectedViaDragHandle should not be set to false
|
|
953
|
-
if (api !== null && api !== void 0 && (_api$blockControls$sh5 = api.blockControls.sharedState.currentState()) !== null && _api$blockControls$sh5 !== void 0 && _api$blockControls$sh5.isSelectedViaDragHandle && !isBlockMenuOpen) {
|
|
954
|
-
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(false));
|
|
955
|
-
}
|
|
901
|
+
}
|
|
902
|
+
if ((event.key === 'Enter' || event.key === ' ') && event.target instanceof HTMLElement && editorExperiment('platform_editor_controls', 'variant1')) {
|
|
903
|
+
const isDragHandle = event.target.closest(editorExperiment('platform_editor_block_menu', true) ? DRAG_HANDLE_SELECTOR : '[data-editor-block-ctrl-drag-handle="true"]') !== null;
|
|
904
|
+
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(isDragHandle));
|
|
905
|
+
}
|
|
906
|
+
if ((event.key === 'ArrowLeft' || event.key === 'ArrowRight' || event.key === 'ArrowDown' || event.key === 'ArrowUp') && editorExperiment('platform_editor_controls', 'variant1')) {
|
|
907
|
+
var _api$blockControls$sh2, _api$blockControls$sh3;
|
|
908
|
+
const isBlockMenuOpen = (api === null || api === void 0 ? void 0 : (_api$blockControls$sh2 = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh2 === void 0 ? void 0 : _api$blockControls$sh2.isMenuOpen) && editorExperiment('platform_editor_block_menu', true);
|
|
909
|
+
// when block menu is just open, and we press arrow keys, we want to use the arrow keys to navigate the block menu
|
|
910
|
+
// in this scenario, isSelectedViaDragHandle should not be set to false
|
|
911
|
+
if (api !== null && api !== void 0 && (_api$blockControls$sh3 = api.blockControls.sharedState.currentState()) !== null && _api$blockControls$sh3 !== void 0 && _api$blockControls$sh3.isSelectedViaDragHandle && !isBlockMenuOpen) {
|
|
912
|
+
api === null || api === void 0 ? void 0 : api.core.actions.execute(api === null || api === void 0 ? void 0 : api.blockControls.commands.setSelectedViaDragHandle(false));
|
|
956
913
|
}
|
|
957
914
|
}
|
|
915
|
+
if (!event.repeat && event.shiftKey && fg('platform_editor_elements_dnd_shift_click_select')) {
|
|
916
|
+
view.dispatch(view.state.tr.setMeta(key, {
|
|
917
|
+
...view.state.tr.getMeta(key),
|
|
918
|
+
isShiftDown: true
|
|
919
|
+
}));
|
|
920
|
+
}
|
|
921
|
+
return false;
|
|
958
922
|
},
|
|
959
923
|
keyup(view, event) {
|
|
960
924
|
var _api$limitedMode9, _api$limitedMode9$sha;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
|
|
2
2
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
3
|
-
export const attachMoveNodeAnalytics = (tr, inputMethod, fromDepth,
|
|
3
|
+
export const attachMoveNodeAnalytics = (tr, inputMethod, fromDepth, fromNodeTypes, toDepth, toNodeType, isSameParent, api, hasSelectedMultipleNodes) => {
|
|
4
4
|
var _api$analytics, _api$analytics$action;
|
|
5
5
|
return 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.attachAnalyticsEvent({
|
|
6
6
|
eventType: EVENT_TYPE.TRACK,
|
|
@@ -9,7 +9,6 @@ export const attachMoveNodeAnalytics = (tr, inputMethod, fromDepth, fromNodeType
|
|
|
9
9
|
actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
|
|
10
10
|
attributes: {
|
|
11
11
|
nodeDepth: fromDepth,
|
|
12
|
-
nodeType: fromNodeType,
|
|
13
12
|
nodeTypes: fromNodeTypes,
|
|
14
13
|
hasSelectedMultipleNodes,
|
|
15
14
|
destinationNodeDepth: toDepth,
|