@atlaskit/editor-plugin-block-controls 2.26.1 → 2.26.2
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 +10 -0
- package/dist/cjs/editor-commands/move-node.js +16 -15
- package/dist/cjs/editor-commands/move-to-layout.js +20 -8
- package/dist/cjs/editor-commands/show-drag-handle.js +89 -3
- package/dist/cjs/pm-plugins/decorations-anchor.js +5 -10
- package/dist/cjs/pm-plugins/decorations-common.js +5 -1
- package/dist/cjs/pm-plugins/main.js +28 -8
- package/dist/cjs/pm-plugins/utils/analytics.js +66 -0
- package/dist/cjs/pm-plugins/utils/selection.js +22 -2
- package/dist/cjs/ui/drag-handle.js +23 -9
- package/dist/es2019/editor-commands/move-node.js +17 -16
- package/dist/es2019/editor-commands/move-to-layout.js +20 -8
- package/dist/es2019/editor-commands/show-drag-handle.js +88 -3
- package/dist/es2019/pm-plugins/decorations-anchor.js +6 -11
- package/dist/es2019/pm-plugins/decorations-common.js +4 -0
- package/dist/es2019/pm-plugins/main.js +24 -6
- package/dist/es2019/pm-plugins/utils/{fire-analytics.js → analytics.js} +31 -3
- package/dist/es2019/pm-plugins/utils/selection.js +22 -1
- package/dist/es2019/ui/drag-handle.js +19 -3
- package/dist/esm/editor-commands/move-node.js +17 -16
- package/dist/esm/editor-commands/move-to-layout.js +20 -8
- package/dist/esm/editor-commands/show-drag-handle.js +88 -2
- package/dist/esm/pm-plugins/decorations-anchor.js +6 -11
- package/dist/esm/pm-plugins/decorations-common.js +4 -0
- package/dist/esm/pm-plugins/main.js +27 -7
- package/dist/esm/pm-plugins/utils/{fire-analytics.js → analytics.js} +32 -3
- package/dist/esm/pm-plugins/utils/selection.js +21 -1
- package/dist/esm/ui/drag-handle.js +22 -4
- package/dist/types/editor-commands/show-drag-handle.d.ts +1 -1
- package/dist/types/pm-plugins/decorations-common.d.ts +1 -0
- package/dist/types/pm-plugins/main.d.ts +1 -0
- package/dist/types/pm-plugins/utils/analytics.d.ts +12 -0
- package/dist/types/pm-plugins/utils/selection.d.ts +9 -0
- package/dist/types-ts4.5/editor-commands/show-drag-handle.d.ts +1 -1
- package/dist/types-ts4.5/pm-plugins/decorations-common.d.ts +1 -0
- package/dist/types-ts4.5/pm-plugins/main.d.ts +1 -0
- package/dist/types-ts4.5/pm-plugins/utils/analytics.d.ts +12 -0
- package/dist/types-ts4.5/pm-plugins/utils/selection.d.ts +9 -0
- package/package.json +10 -4
- package/dist/cjs/pm-plugins/utils/fire-analytics.js +0 -36
- package/dist/types/pm-plugins/utils/fire-analytics.d.ts +0 -5
- package/dist/types-ts4.5/pm-plugins/utils/fire-analytics.d.ts +0 -5
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
});
|
|
7
7
|
exports.DragHandle = void 0;
|
|
8
8
|
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
9
|
+
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
|
|
9
10
|
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
10
11
|
var _react = require("react");
|
|
11
12
|
var _react2 = require("@emotion/react");
|
|
@@ -25,18 +26,17 @@ var _primitives = require("@atlaskit/primitives");
|
|
|
25
26
|
var _experiments = require("@atlaskit/tmp-editor-statsig/experiments");
|
|
26
27
|
var _tooltip = _interopRequireDefault(require("@atlaskit/tooltip"));
|
|
27
28
|
var _main = require("../pm-plugins/main");
|
|
29
|
+
var _analytics2 = require("../pm-plugins/utils/analytics");
|
|
28
30
|
var _dragHandlePositions = require("../pm-plugins/utils/drag-handle-positions");
|
|
29
31
|
var _getNestedNodePosition = require("../pm-plugins/utils/getNestedNodePosition");
|
|
30
32
|
var _getSelection = require("../pm-plugins/utils/getSelection");
|
|
31
33
|
var _consts = require("./consts");
|
|
32
34
|
var _dragPreview = require("./drag-preview");
|
|
33
|
-
|
|
35
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
36
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; } /**
|
|
34
37
|
* @jsxRuntime classic
|
|
35
38
|
* @jsx jsx
|
|
36
|
-
*/
|
|
37
|
-
|
|
38
|
-
// eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
39
|
-
|
|
39
|
+
*/ // eslint-disable-next-line @atlaskit/ui-styling-standard/use-compiled -- Ignored via go/DSP-18766
|
|
40
40
|
var iconWrapperStyles = (0, _primitives.xcss)({
|
|
41
41
|
display: 'flex',
|
|
42
42
|
justifyContent: 'center',
|
|
@@ -263,7 +263,11 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
|
|
|
263
263
|
var isMultiSelect = (0, _experiments.editorExperiment)('platform_editor_element_drag_and_drop_multiselect', true, {
|
|
264
264
|
exposure: true
|
|
265
265
|
});
|
|
266
|
+
var nodeTypes, hasSelectedMultipleNodes;
|
|
267
|
+
var resolvedMovingNode = tr.doc.resolve(start);
|
|
268
|
+
var maybeNode = resolvedMovingNode.nodeAfter;
|
|
266
269
|
if (isMultiSelect) {
|
|
270
|
+
var _tr$getMeta;
|
|
267
271
|
var handlePos = getPos();
|
|
268
272
|
if (typeof handlePos !== 'number') {
|
|
269
273
|
return tr;
|
|
@@ -274,22 +278,32 @@ var DragHandle = exports.DragHandle = function DragHandle(_ref) {
|
|
|
274
278
|
tr: tr
|
|
275
279
|
});
|
|
276
280
|
}
|
|
281
|
+
var multiSelectDnD = (_tr$getMeta = tr.getMeta(_main.key)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.multiSelectDnD;
|
|
282
|
+
if (multiSelectDnD) {
|
|
283
|
+
var attributes = (0, _analytics2.getMultiSelectAnalyticsAttributes)(tr, multiSelectDnD.anchor, multiSelectDnD.head);
|
|
284
|
+
nodeTypes = attributes.nodeTypes;
|
|
285
|
+
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
286
|
+
} else {
|
|
287
|
+
nodeTypes = maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name;
|
|
288
|
+
hasSelectedMultipleNodes = false;
|
|
289
|
+
}
|
|
277
290
|
}
|
|
278
291
|
api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || _api$blockControls2.commands.setNodeDragged(getPos, anchorName, nodeType)({
|
|
279
292
|
tr: tr
|
|
280
293
|
});
|
|
281
|
-
var resolvedMovingNode = tr.doc.resolve(start);
|
|
282
|
-
var maybeNode = resolvedMovingNode.nodeAfter;
|
|
283
294
|
tr.setMeta('scrollIntoView', false);
|
|
284
295
|
api === null || api === void 0 || (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 || _api$analytics3.actions.attachAnalyticsEvent({
|
|
285
296
|
eventType: _analytics.EVENT_TYPE.UI,
|
|
286
297
|
action: _analytics.ACTION.DRAGGED,
|
|
287
298
|
actionSubject: _analytics.ACTION_SUBJECT.ELEMENT,
|
|
288
299
|
actionSubjectId: _analytics.ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
|
|
289
|
-
attributes: {
|
|
300
|
+
attributes: _objectSpread({
|
|
290
301
|
nodeDepth: resolvedMovingNode.depth,
|
|
291
302
|
nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || ''
|
|
292
|
-
}
|
|
303
|
+
}, isMultiSelect && {
|
|
304
|
+
nodeTypes: nodeTypes,
|
|
305
|
+
hasSelectedMultipleNodes: hasSelectedMultipleNodes
|
|
306
|
+
})
|
|
293
307
|
})(tr);
|
|
294
308
|
return tr;
|
|
295
309
|
});
|
|
@@ -11,12 +11,12 @@ import { findTable, isInTable, isTableSelected } from '@atlaskit/editor-tables/u
|
|
|
11
11
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
12
12
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
13
13
|
import { key } from '../pm-plugins/main';
|
|
14
|
+
import { attachMoveNodeAnalytics, getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
|
|
14
15
|
import { DIRECTION } from '../pm-plugins/utils/consts';
|
|
15
|
-
import { attachMoveNodeAnalytics } from '../pm-plugins/utils/fire-analytics';
|
|
16
16
|
import { getNestedNodePosition } from '../pm-plugins/utils/getNestedNodePosition';
|
|
17
17
|
import { selectNode, setCursorPositionAtMovedNode } from '../pm-plugins/utils/getSelection';
|
|
18
18
|
import { removeFromSource } from '../pm-plugins/utils/remove-from-source';
|
|
19
|
-
import {
|
|
19
|
+
import { getSelectedSlicePosition } from '../pm-plugins/utils/selection';
|
|
20
20
|
import { getInsertLayoutStep, updateSelection } from '../pm-plugins/utils/update-selection';
|
|
21
21
|
import { canMoveNodeToIndex, isInsideTable, transformSliceExpandToNestedExpand } from '../pm-plugins/utils/validation';
|
|
22
22
|
|
|
@@ -263,23 +263,21 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
|
|
|
263
263
|
}
|
|
264
264
|
let sliceFrom = start;
|
|
265
265
|
let sliceTo;
|
|
266
|
+
let mappedTo;
|
|
267
|
+
let sourceNodeTypes, hasSelectedMultipleNodes;
|
|
266
268
|
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
|
|
267
269
|
exposure: true
|
|
268
270
|
});
|
|
269
271
|
if (isMultiSelect) {
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
sliceFrom = inSelection ? Math.min(anchor, head) : start;
|
|
277
|
-
const handleSize = (_handleNode$nodeSize = handleNode === null || handleNode === void 0 ? void 0 : handleNode.nodeSize) !== null && _handleNode$nodeSize !== void 0 ? _handleNode$nodeSize : 1;
|
|
278
|
-
const handleEnd = sliceFrom + handleSize;
|
|
279
|
-
sliceTo = inSelection ? Math.max(anchor, head) : handleEnd;
|
|
272
|
+
const slicePosition = getSelectedSlicePosition(start, tr, api);
|
|
273
|
+
sliceFrom = slicePosition.from;
|
|
274
|
+
sliceTo = slicePosition.to;
|
|
275
|
+
const attributes = getMultiSelectAnalyticsAttributes(tr, sliceFrom, sliceTo);
|
|
276
|
+
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
277
|
+
sourceNodeTypes = attributes.nodeTypes;
|
|
280
278
|
} else {
|
|
281
|
-
var _handleNode$
|
|
282
|
-
const size = (_handleNode$
|
|
279
|
+
var _handleNode$nodeSize;
|
|
280
|
+
const size = (_handleNode$nodeSize = handleNode === null || handleNode === void 0 ? void 0 : handleNode.nodeSize) !== null && _handleNode$nodeSize !== void 0 ? _handleNode$nodeSize : 1;
|
|
283
281
|
sliceTo = sliceFrom + size;
|
|
284
282
|
}
|
|
285
283
|
const {
|
|
@@ -288,7 +286,6 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
|
|
|
288
286
|
} = tr.doc.type.schema.nodes;
|
|
289
287
|
const $to = tr.doc.resolve(to);
|
|
290
288
|
const $handlePos = tr.doc.resolve(start);
|
|
291
|
-
let mappedTo;
|
|
292
289
|
if (editorExperiment('nested-dnd', true)) {
|
|
293
290
|
const nodeCopy = tr.doc.slice(sliceFrom, sliceTo, false); // cut the content
|
|
294
291
|
const destType = $to.node().type;
|
|
@@ -344,7 +341,7 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
|
|
|
344
341
|
}
|
|
345
342
|
}
|
|
346
343
|
if (editorExperiment('advanced_layouts', true)) {
|
|
347
|
-
attachMoveNodeAnalytics(tr, inputMethod, $handlePos.depth, handleNode.type.name, $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.depth, $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.parent.type.name, $handlePos.sameParent($mappedTo), api);
|
|
344
|
+
attachMoveNodeAnalytics(tr, inputMethod, $handlePos.depth, handleNode.type.name, $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.depth, $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.parent.type.name, $handlePos.sameParent($mappedTo), api, sourceNodeTypes, hasSelectedMultipleNodes);
|
|
348
345
|
} else {
|
|
349
346
|
var _api$analytics;
|
|
350
347
|
api === null || api === void 0 ? void 0 : (_api$analytics = api.analytics) === null || _api$analytics === void 0 ? void 0 : _api$analytics.actions.attachAnalyticsEvent({
|
|
@@ -359,6 +356,10 @@ export const moveNode = api => (start, to, inputMethod = INPUT_METHOD.DRAG_AND_D
|
|
|
359
356
|
destinationNodeType: $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.parent.type.name,
|
|
360
357
|
...(fg('platform_editor_element_drag_and_drop_ed_23873') && {
|
|
361
358
|
inputMethod
|
|
359
|
+
}),
|
|
360
|
+
...(isMultiSelect && {
|
|
361
|
+
sourceNodeTypes,
|
|
362
|
+
hasSelectedMultipleNodes
|
|
362
363
|
})
|
|
363
364
|
}
|
|
364
365
|
})(tr);
|
|
@@ -4,9 +4,9 @@ import { Fragment, Node as PMNode } from '@atlaskit/editor-prosemirror/model';
|
|
|
4
4
|
import { NodeSelection } from '@atlaskit/editor-prosemirror/state';
|
|
5
5
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
6
6
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
7
|
+
import { fireInsertLayoutAnalytics, attachMoveNodeAnalytics, getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
|
|
7
8
|
import { isFragmentOfType, containsNodeOfType } from '../pm-plugins/utils/check-fragment';
|
|
8
9
|
import { maxLayoutColumnSupported } from '../pm-plugins/utils/consts';
|
|
9
|
-
import { fireInsertLayoutAnalytics, attachMoveNodeAnalytics } from '../pm-plugins/utils/fire-analytics';
|
|
10
10
|
import { removeFromSource } from '../pm-plugins/utils/remove-from-source';
|
|
11
11
|
import { getMultiSelectionIfPosInside } from '../pm-plugins/utils/selection';
|
|
12
12
|
import { updateColumnWidths } from '../pm-plugins/utils/update-column-widths';
|
|
@@ -42,9 +42,14 @@ const createNewLayout = (schema, layoutContents) => {
|
|
|
42
42
|
const moveToExistingLayout = (toLayout, toLayoutPos, sourceContent, from, to, tr, $originalFrom, $originalTo, api, selectMovedNode) => {
|
|
43
43
|
const isSameLayout = isInSameLayout($originalFrom, $originalTo);
|
|
44
44
|
let sourceContentEndPos = -1;
|
|
45
|
-
|
|
45
|
+
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
|
|
46
|
+
let sourceNodeTypes, hasSelectedMultipleNodes;
|
|
47
|
+
if (isMultiSelect) {
|
|
46
48
|
if (sourceContent instanceof Fragment) {
|
|
47
49
|
sourceContentEndPos = from + sourceContent.size;
|
|
50
|
+
const attributes = getMultiSelectAnalyticsAttributes(tr, from, sourceContentEndPos);
|
|
51
|
+
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
52
|
+
sourceNodeTypes = attributes.nodeTypes;
|
|
48
53
|
}
|
|
49
54
|
} else {
|
|
50
55
|
if (sourceContent instanceof PMNode) {
|
|
@@ -63,7 +68,7 @@ const moveToExistingLayout = (toLayout, toLayoutPos, sourceContent, from, to, tr
|
|
|
63
68
|
if (!fg('platform_editor_advanced_layouts_post_fix_patch_1') || selectMovedNode) {
|
|
64
69
|
tr.setSelection(new NodeSelection(tr.doc.resolve(mappedTo))).scrollIntoView();
|
|
65
70
|
}
|
|
66
|
-
attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth, ((_$originalFrom$nodeAf = $originalFrom.nodeAfter) === null || _$originalFrom$nodeAf === void 0 ? void 0 : _$originalFrom$nodeAf.type.name) || '', 1, 'layoutSection', true, api);
|
|
71
|
+
attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth, ((_$originalFrom$nodeAf = $originalFrom.nodeAfter) === null || _$originalFrom$nodeAf === void 0 ? void 0 : _$originalFrom$nodeAf.type.name) || '', 1, 'layoutSection', true, api, sourceNodeTypes, hasSelectedMultipleNodes);
|
|
67
72
|
} else if (toLayout.childCount < maxLayoutColumnSupported()) {
|
|
68
73
|
var _$originalFrom$nodeAf2;
|
|
69
74
|
if (fg('platform_editor_advanced_layouts_post_fix_patch_1')) {
|
|
@@ -74,7 +79,7 @@ const moveToExistingLayout = (toLayout, toLayoutPos, sourceContent, from, to, tr
|
|
|
74
79
|
const mappedFrom = tr.mapping.map(from);
|
|
75
80
|
removeFromSource(tr, tr.doc.resolve(mappedFrom), tr.mapping.map(sourceContentEndPos));
|
|
76
81
|
}
|
|
77
|
-
attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth, ((_$originalFrom$nodeAf2 = $originalFrom.nodeAfter) === null || _$originalFrom$nodeAf2 === void 0 ? void 0 : _$originalFrom$nodeAf2.type.name) || '', 1, 'layoutSection', false, api);
|
|
82
|
+
attachMoveNodeAnalytics(tr, INPUT_METHOD.DRAG_AND_DROP, $originalFrom.depth, ((_$originalFrom$nodeAf2 = $originalFrom.nodeAfter) === null || _$originalFrom$nodeAf2 === void 0 ? void 0 : _$originalFrom$nodeAf2.type.name) || '', 1, 'layoutSection', false, api, sourceNodeTypes, hasSelectedMultipleNodes);
|
|
78
83
|
}
|
|
79
84
|
return tr;
|
|
80
85
|
};
|
|
@@ -197,7 +202,7 @@ const canMoveToLayout = (api, from, to, tr, moveNodeAtCursorPos) => {
|
|
|
197
202
|
anchor,
|
|
198
203
|
head
|
|
199
204
|
} = getMultiSelectionIfPosInside(api, from);
|
|
200
|
-
if (anchor && head) {
|
|
205
|
+
if (anchor !== undefined && head !== undefined) {
|
|
201
206
|
sourceFrom = Math.min(anchor, head);
|
|
202
207
|
sourceTo = Math.max(anchor, head);
|
|
203
208
|
sourceContent = tr.doc.slice(sourceFrom, sourceTo).content;
|
|
@@ -249,7 +254,7 @@ const getBreakoutMode = (content, breakout) => {
|
|
|
249
254
|
if (editorExperiment('platform_editor_element_drag_and_drop_multiselect', true)) {
|
|
250
255
|
if (content instanceof PMNode) {
|
|
251
256
|
var _content$marks$find;
|
|
252
|
-
return (_content$marks$find = content.marks.find(m => m.type === breakout)) === null || _content$marks$find === void 0 ? void 0 : _content$marks$find.attrs;
|
|
257
|
+
return (_content$marks$find = content.marks.find(m => m.type === breakout)) === null || _content$marks$find === void 0 ? void 0 : _content$marks$find.attrs.mode;
|
|
253
258
|
} else if (content instanceof Fragment) {
|
|
254
259
|
// Find the first breakout mode in the fragment
|
|
255
260
|
let firstBreakoutMode;
|
|
@@ -308,6 +313,7 @@ export const moveToLayout = api => (from, to, options) => ({
|
|
|
308
313
|
if (!fromContentWithoutBreakout) {
|
|
309
314
|
return tr;
|
|
310
315
|
}
|
|
316
|
+
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
|
|
311
317
|
if (toNode.type === layoutSection) {
|
|
312
318
|
const toPos = options !== null && options !== void 0 && options.moveToEnd ? to + toNode.nodeSize - 1 : to + 1;
|
|
313
319
|
return moveToExistingLayout(toNode, to, fromContentWithoutBreakout, $sourceFrom.pos, toPos, tr, $sourceFrom, $to, api, options === null || options === void 0 ? void 0 : options.selectMovedNode);
|
|
@@ -325,7 +331,7 @@ export const moveToLayout = api => (from, to, options) => ({
|
|
|
325
331
|
// resolve again the source node after node updated (remove breakout marks)
|
|
326
332
|
toNodeWithoutBreakout = tr.doc.resolve(to).nodeAfter || toNode;
|
|
327
333
|
}
|
|
328
|
-
if (
|
|
334
|
+
if (isMultiSelect) {
|
|
329
335
|
if (isFragmentOfType(fromContentWithoutBreakout, 'layoutColumn') && fromContentWithoutBreakout.firstChild) {
|
|
330
336
|
fromContentWithoutBreakout = fromContentWithoutBreakout.firstChild.content;
|
|
331
337
|
}
|
|
@@ -337,6 +343,12 @@ export const moveToLayout = api => (from, to, options) => ({
|
|
|
337
343
|
const layoutContents = options !== null && options !== void 0 && options.moveToEnd ? [toNodeWithoutBreakout, fromContentWithoutBreakout] : [fromContentWithoutBreakout, toNodeWithoutBreakout];
|
|
338
344
|
const newLayout = createNewLayout(tr.doc.type.schema, layoutContents);
|
|
339
345
|
if (newLayout) {
|
|
346
|
+
let sourceNodeTypes, hasSelectedMultipleNodes;
|
|
347
|
+
if (isMultiSelect) {
|
|
348
|
+
const attributes = getMultiSelectAnalyticsAttributes(tr, $sourceFrom.pos, sourceTo);
|
|
349
|
+
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
350
|
+
sourceNodeTypes = attributes.nodeTypes;
|
|
351
|
+
}
|
|
340
352
|
tr = removeFromSource(tr, $sourceFrom, sourceTo);
|
|
341
353
|
const mappedTo = tr.mapping.map(to);
|
|
342
354
|
tr.delete(mappedTo, mappedTo + toNodeWithoutBreakout.nodeSize).insert(mappedTo, newLayout);
|
|
@@ -346,7 +358,7 @@ export const moveToLayout = api => (from, to, options) => ({
|
|
|
346
358
|
breakoutMode && tr.setNodeMarkup(mappedTo, newLayout.type, newLayout.attrs, [breakout.create({
|
|
347
359
|
mode: breakoutMode
|
|
348
360
|
})]);
|
|
349
|
-
fireInsertLayoutAnalytics(tr, api);
|
|
361
|
+
fireInsertLayoutAnalytics(tr, api, sourceNodeTypes, hasSelectedMultipleNodes);
|
|
350
362
|
}
|
|
351
363
|
return tr;
|
|
352
364
|
}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
import { findParentNodeOfType } from '@atlaskit/editor-prosemirror/utils';
|
|
1
2
|
import { isInTable } from '@atlaskit/editor-tables/utils';
|
|
3
|
+
import { fg } from '@atlaskit/platform-feature-flags';
|
|
2
4
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
3
|
-
import {
|
|
5
|
+
import { findNodeDecs } from '../pm-plugins/decorations-anchor';
|
|
6
|
+
import { getDecorations, key } from '../pm-plugins/main';
|
|
4
7
|
import { getNestedNodePosition } from '../pm-plugins/utils/getNestedNodePosition';
|
|
5
|
-
|
|
8
|
+
const showDragHandleAtSelectionOld = (api, shouldFocusParentNode) => (state, _, view) => {
|
|
6
9
|
const {
|
|
7
10
|
$from
|
|
8
11
|
} = state.selection;
|
|
@@ -63,4 +66,86 @@ export const showDragHandleAtSelection = (api, shouldFocusParentNode) => (state,
|
|
|
63
66
|
}
|
|
64
67
|
}
|
|
65
68
|
return false;
|
|
66
|
-
};
|
|
69
|
+
};
|
|
70
|
+
const findParentPosForHandle = state => {
|
|
71
|
+
var _activeNode$handleOpt2;
|
|
72
|
+
const {
|
|
73
|
+
selection: {
|
|
74
|
+
$from
|
|
75
|
+
}
|
|
76
|
+
} = state;
|
|
77
|
+
const {
|
|
78
|
+
activeNode
|
|
79
|
+
} = key.getState(state) || {};
|
|
80
|
+
|
|
81
|
+
// if a node handle is already focused, return the parent pos of that node (with focused handle)
|
|
82
|
+
if (activeNode && (_activeNode$handleOpt2 = activeNode.handleOptions) !== null && _activeNode$handleOpt2 !== void 0 && _activeNode$handleOpt2.isFocused) {
|
|
83
|
+
const $activeNodePos = state.doc.resolve(activeNode.pos);
|
|
84
|
+
|
|
85
|
+
// if the handle is at the top level already, do nothing
|
|
86
|
+
if ($activeNodePos.depth === 0) {
|
|
87
|
+
return undefined;
|
|
88
|
+
}
|
|
89
|
+
return $activeNodePos.before();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// if we are in second level of nested node, we should focus the node at level 1
|
|
93
|
+
if ($from.depth <= 1) {
|
|
94
|
+
return $from.before(1);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// if we are inside a table, we should focus the table's handle
|
|
98
|
+
const parentTableNode = findParentNodeOfType([state.schema.nodes.table])(state.selection);
|
|
99
|
+
if (parentTableNode) {
|
|
100
|
+
return parentTableNode.pos;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// else find closest parent node
|
|
104
|
+
return getNestedNodePosition(state);
|
|
105
|
+
};
|
|
106
|
+
const findNextAnchorDecoration = state => {
|
|
107
|
+
const decorations = getDecorations(state);
|
|
108
|
+
if (!decorations) {
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
const nextHandleNodePos = findParentPosForHandle(state);
|
|
112
|
+
if (nextHandleNodePos === undefined) {
|
|
113
|
+
return undefined;
|
|
114
|
+
}
|
|
115
|
+
const nextHandleNode = state.doc.nodeAt(nextHandleNodePos);
|
|
116
|
+
let nodeDecorations = nextHandleNode && findNodeDecs(decorations, nextHandleNodePos, nextHandleNodePos + nextHandleNode.nodeSize);
|
|
117
|
+
if (!nodeDecorations || nodeDecorations.length === 0) {
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
// ensure the decoration covers the position of the look up node
|
|
122
|
+
nodeDecorations = nodeDecorations.filter(decoration => {
|
|
123
|
+
return decoration.from <= nextHandleNodePos;
|
|
124
|
+
});
|
|
125
|
+
if (nodeDecorations.length === 0) {
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// sort the decorations by the position of the node
|
|
130
|
+
// so we can find the closest decoration to the node
|
|
131
|
+
nodeDecorations.sort((a, b) => {
|
|
132
|
+
if (a.from === b.from) {
|
|
133
|
+
return a.to - b.to;
|
|
134
|
+
}
|
|
135
|
+
return b.from - a.from;
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
// return the closest decoration to the node
|
|
139
|
+
return nodeDecorations[0];
|
|
140
|
+
};
|
|
141
|
+
const showDragHandleAtSelectionNew = api => state => {
|
|
142
|
+
const decoration = findNextAnchorDecoration(state);
|
|
143
|
+
if (api && decoration) {
|
|
144
|
+
api.core.actions.execute(api.blockControls.commands.showDragHandleAt(decoration.from, decoration.spec.anchorName, decoration.spec.nodeTypeWithLevel, {
|
|
145
|
+
isFocused: true
|
|
146
|
+
}));
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
return false;
|
|
150
|
+
};
|
|
151
|
+
export const showDragHandleAtSelection = api => (state, dispatch, view) => editorExperiment('nested-dnd', true) && fg('platform_editor_advanced_layouts_a11y') ? showDragHandleAtSelectionNew(api)(state) : showDragHandleAtSelectionOld(api)(state, dispatch, view);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Decoration } from '@atlaskit/editor-prosemirror/view';
|
|
2
2
|
import { fg } from '@atlaskit/platform-feature-flags';
|
|
3
3
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
4
|
-
import { getNestedDepth, getNodeAnchor, TYPE_NODE_DEC } from './decorations-common';
|
|
4
|
+
import { getNestedDepth, getNodeAnchor, getNodeTypeWithLevel, TYPE_NODE_DEC } from './decorations-common';
|
|
5
5
|
const IGNORE_NODES = ['tableCell', 'tableHeader', 'tableRow', 'listItem', 'caption', 'layoutColumn'];
|
|
6
6
|
const IGNORE_NODES_NEXT = ['tableCell', 'tableHeader', 'tableRow', 'listItem', 'caption'];
|
|
7
7
|
const IGNORE_NODE_DESCENDANTS = ['listItem', 'taskList', 'decisionList', 'mediaSingle'];
|
|
@@ -68,11 +68,10 @@ export const nodeDecorations = (newState, from, to) => {
|
|
|
68
68
|
const ignore_nodes = editorExperiment('advanced_layouts', true) ? IGNORE_NODES_NEXT : IGNORE_NODES;
|
|
69
69
|
newState.doc.nodesBetween(docFrom, docTo, (node, pos, parent, index) => {
|
|
70
70
|
let depth = 0;
|
|
71
|
-
let anchorName;
|
|
72
71
|
const shouldDescend = shouldDescendIntoNode(node);
|
|
73
|
-
anchorName = getNodeAnchor(node);
|
|
72
|
+
const anchorName = getNodeAnchor(node);
|
|
73
|
+
const nodeTypeWithLevel = getNodeTypeWithLevel(node);
|
|
74
74
|
if (editorExperiment('nested-dnd', true)) {
|
|
75
|
-
var _anchorName;
|
|
76
75
|
// Doesn't descend into a node
|
|
77
76
|
if (node.isInline) {
|
|
78
77
|
return false;
|
|
@@ -81,22 +80,18 @@ export const nodeDecorations = (newState, from, to) => {
|
|
|
81
80
|
if (shouldIgnoreNode(node, ignore_nodes, depth, parent)) {
|
|
82
81
|
return shouldDescend; //skip over, don't consider it a valid depth
|
|
83
82
|
}
|
|
84
|
-
anchorName = (_anchorName = anchorName) !== null && _anchorName !== void 0 ? _anchorName : `--node-anchor-${node.type.name}-${pos}`;
|
|
85
|
-
} else {
|
|
86
|
-
var _anchorName2;
|
|
87
|
-
anchorName = (_anchorName2 = anchorName) !== null && _anchorName2 !== void 0 ? _anchorName2 : `--node-anchor-${node.type.name}-${index}`;
|
|
88
83
|
}
|
|
89
84
|
const anchorStyles = `anchor-name: ${anchorName};`;
|
|
90
|
-
const subType = node.attrs.level ? `-${node.attrs.level}` : '';
|
|
91
85
|
decs.push(Decoration.node(pos, pos + node.nodeSize, {
|
|
92
86
|
style: anchorStyles,
|
|
93
87
|
['data-drag-handler-anchor-name']: anchorName,
|
|
94
|
-
['data-drag-handler-node-type']:
|
|
88
|
+
['data-drag-handler-node-type']: nodeTypeWithLevel,
|
|
95
89
|
['data-drag-handler-anchor-depth']: `${depth}`
|
|
96
90
|
}, {
|
|
97
91
|
type: TYPE_NODE_DEC,
|
|
98
92
|
anchorName,
|
|
99
|
-
nodeType: node.type.name
|
|
93
|
+
nodeType: node.type.name,
|
|
94
|
+
nodeTypeWithLevel
|
|
100
95
|
}));
|
|
101
96
|
return shouldDescend && depth < getNestedDepth();
|
|
102
97
|
});
|
|
@@ -9,6 +9,10 @@ export const getNodeAnchor = node => {
|
|
|
9
9
|
const handleId = ObjHash.getForNode(node);
|
|
10
10
|
return `--node-anchor-${node.type.name}-${handleId}`;
|
|
11
11
|
};
|
|
12
|
+
export const getNodeTypeWithLevel = node => {
|
|
13
|
+
const subType = node.attrs.level ? `-${node.attrs.level}` : '';
|
|
14
|
+
return node.type.name + subType;
|
|
15
|
+
};
|
|
12
16
|
class ObjHash {
|
|
13
17
|
static getForNode(node) {
|
|
14
18
|
if (this.caching.has(node)) {
|
|
@@ -18,7 +18,9 @@ import { dropTargetDecorations, findDropTargetDecs } from './decorations-drop-ta
|
|
|
18
18
|
import { handleMouseOver } from './handle-mouse-over';
|
|
19
19
|
import { boundKeydownHandler } from './keymap';
|
|
20
20
|
import { defaultActiveAnchorTracker } from './utils/active-anchor-tracker';
|
|
21
|
+
import { getMultiSelectAnalyticsAttributes } from './utils/analytics';
|
|
21
22
|
import { AnchorRectCache, isAnchorSupported } from './utils/anchor-utils';
|
|
23
|
+
import { getSelectedSlicePosition } from './utils/selection';
|
|
22
24
|
import { getTrMetadata } from './utils/transactions';
|
|
23
25
|
export const key = new PluginKey('blockControls');
|
|
24
26
|
const EDITOR_BLOCKS_DRAG_INIT = 'Editor Blocks Drag Initialization Time';
|
|
@@ -73,7 +75,8 @@ const destroyFn = (api, editorView) => {
|
|
|
73
75
|
api === null || api === void 0 ? void 0 : (_api$core = api.core) === null || _api$core === void 0 ? void 0 : _api$core.actions.execute(({
|
|
74
76
|
tr
|
|
75
77
|
}) => {
|
|
76
|
-
|
|
78
|
+
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
|
|
79
|
+
if (isMultiSelect) {
|
|
77
80
|
var _api$blockControls, _api$selection;
|
|
78
81
|
const {
|
|
79
82
|
multiSelectDnD
|
|
@@ -96,6 +99,13 @@ const destroyFn = (api, editorView) => {
|
|
|
96
99
|
// if no drop targets are rendered, assume that drop is invalid
|
|
97
100
|
if (location.current.dropTargets.length === 0) {
|
|
98
101
|
var _api$analytics2;
|
|
102
|
+
let nodeTypes, hasSelectedMultipleNodes;
|
|
103
|
+
if (isMultiSelect && api) {
|
|
104
|
+
const position = getSelectedSlicePosition(start, tr, api);
|
|
105
|
+
const attributes = getMultiSelectAnalyticsAttributes(tr, position.from, position.to);
|
|
106
|
+
nodeTypes = attributes.nodeTypes;
|
|
107
|
+
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
108
|
+
}
|
|
99
109
|
const resolvedMovingNode = tr.doc.resolve(start);
|
|
100
110
|
const maybeNode = resolvedMovingNode.nodeAfter;
|
|
101
111
|
api === null || api === void 0 ? void 0 : (_api$analytics2 = api.analytics) === null || _api$analytics2 === void 0 ? void 0 : _api$analytics2.actions.attachAnalyticsEvent({
|
|
@@ -105,7 +115,11 @@ const destroyFn = (api, editorView) => {
|
|
|
105
115
|
actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
|
|
106
116
|
attributes: {
|
|
107
117
|
nodeDepth: resolvedMovingNode.depth,
|
|
108
|
-
nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || ''
|
|
118
|
+
nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || '',
|
|
119
|
+
...(isMultiSelect && {
|
|
120
|
+
nodeTypes,
|
|
121
|
+
hasSelectedMultipleNodes
|
|
122
|
+
})
|
|
109
123
|
}
|
|
110
124
|
})(tr);
|
|
111
125
|
}
|
|
@@ -131,6 +145,10 @@ const initialState = {
|
|
|
131
145
|
isPMDragging: false,
|
|
132
146
|
multiSelectDnD: undefined
|
|
133
147
|
};
|
|
148
|
+
export const getDecorations = state => {
|
|
149
|
+
var _key$getState;
|
|
150
|
+
return (_key$getState = key.getState(state)) === null || _key$getState === void 0 ? void 0 : _key$getState.decorations;
|
|
151
|
+
};
|
|
134
152
|
export const newApply = (api, formatMessage, tr, currentState, newState, flags, nodeViewPortalProviderAPI, anchorRectCache) => {
|
|
135
153
|
var _meta$activeNode, _activeNode, _activeNode2, _meta$activeNode$hand, _meta$isDragging, _meta$isDragging2, _meta$editorHeight, _meta$editorWidthLeft, _meta$editorWidthRigh, _meta$isPMDragging, _meta$multiSelectDnD;
|
|
136
154
|
let {
|
|
@@ -452,12 +470,12 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI) => {
|
|
|
452
470
|
},
|
|
453
471
|
props: {
|
|
454
472
|
decorations: state => {
|
|
455
|
-
var _api$editorDisabled, _api$editorDisabled$s, _key$
|
|
473
|
+
var _api$editorDisabled, _api$editorDisabled$s, _key$getState2;
|
|
456
474
|
const isDisabled = api === null || api === void 0 ? void 0 : (_api$editorDisabled = api.editorDisabled) === null || _api$editorDisabled === void 0 ? void 0 : (_api$editorDisabled$s = _api$editorDisabled.sharedState.currentState()) === null || _api$editorDisabled$s === void 0 ? void 0 : _api$editorDisabled$s.editorDisabled;
|
|
457
475
|
if (isDisabled) {
|
|
458
476
|
return;
|
|
459
477
|
}
|
|
460
|
-
return (_key$
|
|
478
|
+
return (_key$getState2 = key.getState(state)) === null || _key$getState2 === void 0 ? void 0 : _key$getState2.decorations;
|
|
461
479
|
},
|
|
462
480
|
handleDOMEvents: {
|
|
463
481
|
drop(view, event) {
|
|
@@ -532,12 +550,12 @@ export const createPlugin = (api, getIntl, nodeViewPortalProviderAPI) => {
|
|
|
532
550
|
}));
|
|
533
551
|
},
|
|
534
552
|
dragend(view) {
|
|
535
|
-
var _key$
|
|
553
|
+
var _key$getState3;
|
|
536
554
|
const {
|
|
537
555
|
state,
|
|
538
556
|
dispatch
|
|
539
557
|
} = view;
|
|
540
|
-
if ((_key$
|
|
558
|
+
if ((_key$getState3 = key.getState(state)) !== null && _key$getState3 !== void 0 && _key$getState3.isPMDragging) {
|
|
541
559
|
dispatch(state.tr.setMeta(key, {
|
|
542
560
|
isPMDragging: false
|
|
543
561
|
}));
|
|
@@ -1,5 +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, fromNodeType, toDepth, toNodeType, isSameParent, api, fromNodeTypes, hasSelectedMultipleNodes) => {
|
|
3
4
|
var _api$analytics, _api$analytics$action;
|
|
4
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({
|
|
5
6
|
eventType: EVENT_TYPE.TRACK,
|
|
@@ -9,6 +10,8 @@ export const attachMoveNodeAnalytics = (tr, inputMethod, fromDepth, fromNodeType
|
|
|
9
10
|
attributes: {
|
|
10
11
|
nodeDepth: fromDepth,
|
|
11
12
|
nodeType: fromNodeType,
|
|
13
|
+
nodeTypes: fromNodeTypes,
|
|
14
|
+
hasSelectedMultipleNodes,
|
|
12
15
|
destinationNodeDepth: toDepth,
|
|
13
16
|
destinationNodeType: toNodeType,
|
|
14
17
|
isSameParent: isSameParent,
|
|
@@ -16,15 +19,40 @@ export const attachMoveNodeAnalytics = (tr, inputMethod, fromDepth, fromNodeType
|
|
|
16
19
|
}
|
|
17
20
|
})(tr);
|
|
18
21
|
};
|
|
19
|
-
export const fireInsertLayoutAnalytics = (tr, api) => {
|
|
22
|
+
export const fireInsertLayoutAnalytics = (tr, api, nodeTypes, hasSelectedMultipleNodes) => {
|
|
20
23
|
var _api$analytics2, _api$analytics2$actio;
|
|
21
24
|
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.attachAnalyticsEvent({
|
|
22
25
|
action: ACTION.INSERTED,
|
|
23
26
|
actionSubject: ACTION_SUBJECT.DOCUMENT,
|
|
24
27
|
actionSubjectId: ACTION_SUBJECT_ID.LAYOUT,
|
|
25
28
|
attributes: {
|
|
26
|
-
inputMethod: INPUT_METHOD.DRAG_AND_DROP
|
|
29
|
+
inputMethod: INPUT_METHOD.DRAG_AND_DROP,
|
|
30
|
+
nodeTypes,
|
|
31
|
+
hasSelectedMultipleNodes
|
|
27
32
|
},
|
|
28
33
|
eventType: EVENT_TYPE.TRACK
|
|
29
34
|
})(tr);
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Given a range, return distinctive types of node and whether there are multiple nodes in the range
|
|
39
|
+
*/
|
|
40
|
+
export const getMultiSelectAnalyticsAttributes = (tr, anchor, head) => {
|
|
41
|
+
const nodeTypes = [];
|
|
42
|
+
const from = Math.min(anchor, head);
|
|
43
|
+
const to = Math.max(anchor, head);
|
|
44
|
+
tr.doc.nodesBetween(from, to, (node, pos) => {
|
|
45
|
+
if (pos < from) {
|
|
46
|
+
// ignore parent node
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
nodeTypes.push(node.type.name);
|
|
50
|
+
|
|
51
|
+
// only care about the top level (relatively in the range) nodes
|
|
52
|
+
return false;
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
nodeTypes: fg('platform_editor_track_node_types') ? [...new Set(nodeTypes)].sort().join(',') : undefined,
|
|
56
|
+
hasSelectedMultipleNodes: nodeTypes.length > 1
|
|
57
|
+
};
|
|
30
58
|
};
|
|
@@ -2,7 +2,7 @@ export const getMultiSelectionIfPosInside = (api, pos) => {
|
|
|
2
2
|
var _api$blockControls;
|
|
3
3
|
const {
|
|
4
4
|
multiSelectDnD
|
|
5
|
-
} = (
|
|
5
|
+
} = ((_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 ? void 0 : _api$blockControls.sharedState.currentState()) || {};
|
|
6
6
|
if (multiSelectDnD && multiSelectDnD.anchor >= 0 && multiSelectDnD.head >= 0) {
|
|
7
7
|
const multiFrom = Math.min(multiSelectDnD.anchor, multiSelectDnD.head);
|
|
8
8
|
const multiTo = Math.max(multiSelectDnD.anchor, multiSelectDnD.head);
|
|
@@ -14,4 +14,25 @@ export const getMultiSelectionIfPosInside = (api, pos) => {
|
|
|
14
14
|
} : {};
|
|
15
15
|
}
|
|
16
16
|
return {};
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
*
|
|
21
|
+
* @returns from and to positions of the selected content (after expansion)
|
|
22
|
+
*/
|
|
23
|
+
export const getSelectedSlicePosition = (handlePos, tr, api) => {
|
|
24
|
+
var _activeNode$nodeSize;
|
|
25
|
+
const {
|
|
26
|
+
anchor,
|
|
27
|
+
head
|
|
28
|
+
} = getMultiSelectionIfPosInside(api, handlePos);
|
|
29
|
+
const inSelection = anchor !== undefined && head !== undefined;
|
|
30
|
+
const from = inSelection ? Math.min(anchor, head) : handlePos;
|
|
31
|
+
const activeNode = tr.doc.nodeAt(handlePos);
|
|
32
|
+
const activeNodeEndPos = handlePos + ((_activeNode$nodeSize = activeNode === null || activeNode === void 0 ? void 0 : activeNode.nodeSize) !== null && _activeNode$nodeSize !== void 0 ? _activeNode$nodeSize : 1);
|
|
33
|
+
const to = inSelection ? Math.max(anchor, head) : activeNodeEndPos;
|
|
34
|
+
return {
|
|
35
|
+
from,
|
|
36
|
+
to
|
|
37
|
+
};
|
|
17
38
|
};
|
|
@@ -21,6 +21,7 @@ import { Box, xcss } from '@atlaskit/primitives';
|
|
|
21
21
|
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
|
|
22
22
|
import Tooltip from '@atlaskit/tooltip';
|
|
23
23
|
import { key } from '../pm-plugins/main';
|
|
24
|
+
import { getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
|
|
24
25
|
import { getLeftPosition, getTopPosition } from '../pm-plugins/utils/drag-handle-positions';
|
|
25
26
|
import { getNestedNodePosition } from '../pm-plugins/utils/getNestedNodePosition';
|
|
26
27
|
import { isHandleInSelection, selectNode } from '../pm-plugins/utils/getSelection';
|
|
@@ -246,7 +247,11 @@ export const DragHandle = ({
|
|
|
246
247
|
const isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true, {
|
|
247
248
|
exposure: true
|
|
248
249
|
});
|
|
250
|
+
let nodeTypes, hasSelectedMultipleNodes;
|
|
251
|
+
const resolvedMovingNode = tr.doc.resolve(start);
|
|
252
|
+
const maybeNode = resolvedMovingNode.nodeAfter;
|
|
249
253
|
if (isMultiSelect) {
|
|
254
|
+
var _tr$getMeta;
|
|
250
255
|
const handlePos = getPos();
|
|
251
256
|
if (typeof handlePos !== 'number') {
|
|
252
257
|
return tr;
|
|
@@ -257,12 +262,19 @@ export const DragHandle = ({
|
|
|
257
262
|
tr
|
|
258
263
|
});
|
|
259
264
|
}
|
|
265
|
+
const multiSelectDnD = (_tr$getMeta = tr.getMeta(key)) === null || _tr$getMeta === void 0 ? void 0 : _tr$getMeta.multiSelectDnD;
|
|
266
|
+
if (multiSelectDnD) {
|
|
267
|
+
const attributes = getMultiSelectAnalyticsAttributes(tr, multiSelectDnD.anchor, multiSelectDnD.head);
|
|
268
|
+
nodeTypes = attributes.nodeTypes;
|
|
269
|
+
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
|
|
270
|
+
} else {
|
|
271
|
+
nodeTypes = maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name;
|
|
272
|
+
hasSelectedMultipleNodes = false;
|
|
273
|
+
}
|
|
260
274
|
}
|
|
261
275
|
api === null || api === void 0 ? void 0 : (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.commands.setNodeDragged(getPos, anchorName, nodeType)({
|
|
262
276
|
tr
|
|
263
277
|
});
|
|
264
|
-
const resolvedMovingNode = tr.doc.resolve(start);
|
|
265
|
-
const maybeNode = resolvedMovingNode.nodeAfter;
|
|
266
278
|
tr.setMeta('scrollIntoView', false);
|
|
267
279
|
api === null || api === void 0 ? void 0 : (_api$analytics3 = api.analytics) === null || _api$analytics3 === void 0 ? void 0 : _api$analytics3.actions.attachAnalyticsEvent({
|
|
268
280
|
eventType: EVENT_TYPE.UI,
|
|
@@ -271,7 +283,11 @@ export const DragHandle = ({
|
|
|
271
283
|
actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
|
|
272
284
|
attributes: {
|
|
273
285
|
nodeDepth: resolvedMovingNode.depth,
|
|
274
|
-
nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || ''
|
|
286
|
+
nodeType: (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.type.name) || '',
|
|
287
|
+
...(isMultiSelect && {
|
|
288
|
+
nodeTypes,
|
|
289
|
+
hasSelectedMultipleNodes
|
|
290
|
+
})
|
|
275
291
|
}
|
|
276
292
|
})(tr);
|
|
277
293
|
return tr;
|