@atlaskit/editor-plugin-block-controls
Version:
Block controls plugin for @atlaskit/editor-core
479 lines (470 loc) • 26.4 kB
JavaScript
import _defineProperty from "@babel/runtime/helpers/defineProperty";
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; }
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) { _defineProperty(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; }
import { ACTION, ACTION_SUBJECT, ACTION_SUBJECT_ID, EVENT_TYPE, INPUT_METHOD } from '@atlaskit/editor-common/analytics';
import { expandedState } from '@atlaskit/editor-common/expand';
import { blockControlsMessages } from '@atlaskit/editor-common/messages';
import { expandSelectionBounds, GapCursorSelection } from '@atlaskit/editor-common/selection';
import { transformSliceNestedExpandToExpand } from '@atlaskit/editor-common/transforms';
import { DIRECTION } from '@atlaskit/editor-common/types';
import { isEmptyParagraph } from '@atlaskit/editor-common/utils';
import { Fragment, Slice } from '@atlaskit/editor-prosemirror/model';
import { NodeSelection, Selection } from '@atlaskit/editor-prosemirror/state';
import { Mapping, StepMap } from '@atlaskit/editor-prosemirror/transform';
import { findChildrenByType, findParentNodeOfType, findParentNodeOfTypeClosestToPos } from '@atlaskit/editor-prosemirror/utils';
import { findTable, isInTable, isTableSelected } from '@atlaskit/editor-tables/utils';
import { fg } from '@atlaskit/platform-feature-flags';
import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments';
import { key } from '../pm-plugins/main';
import { attachMoveNodeAnalytics, getMultiSelectAnalyticsAttributes } from '../pm-plugins/utils/analytics';
import { getNestedNodePosition } from '../pm-plugins/utils/getNestedNodePosition';
import { selectNode, setCursorPositionAtMovedNode } from '../pm-plugins/utils/getSelection';
import { removeFromSource } from '../pm-plugins/utils/remove-from-source';
import { getSelectedSlicePosition } from '../pm-plugins/utils/selection';
import { getInsertLayoutStep, updateSelection } from '../pm-plugins/utils/update-selection';
import { canMoveNodeToIndex, isInsideTable, transformFragmentExpandToNestedExpand, transformSliceExpandToNestedExpand } from '../pm-plugins/utils/validation';
import { getPosWhenMoveNodeDown, getPosWhenMoveNodeUp } from './utils/move-node-utils';
/**
* This function transforms the slice to move
* @param nodeCopy The slice contains the node to be moved
* @param destType The type of the destiation node
* @returns transformed slice or null if unable to
*/
function transformSourceSlice(nodeCopy, destType) {
var srcNode = nodeCopy.content.firstChild;
var schema = srcNode === null || srcNode === void 0 ? void 0 : srcNode.type.schema;
if (!schema) {
return nodeCopy;
}
var _schema$nodes = schema.nodes,
doc = _schema$nodes.doc,
layoutColumn = _schema$nodes.layoutColumn;
var destTypeInTable = isInsideTable(destType);
var destTypeInDocOrLayoutCol = [doc, layoutColumn].includes(destType);
// No need to loop over slice content if destination requires no transformations
if (!destTypeInTable && !destTypeInDocOrLayoutCol) {
return nodeCopy;
}
var containsExpand = false;
var containsNestedExpand = false;
for (var i = 0; i < nodeCopy.content.childCount; i++) {
var node = nodeCopy.content.child(i);
if (node.type === schema.nodes.expand) {
containsExpand = true;
} else if (node.type === schema.nodes.nestedExpand) {
containsNestedExpand = true;
}
if (containsExpand && containsNestedExpand) {
break;
}
}
if (containsExpand && destTypeInTable) {
return transformSliceExpandToNestedExpand(nodeCopy);
} else if (containsNestedExpand && destTypeInDocOrLayoutCol) {
return transformSliceNestedExpandToExpand(nodeCopy, schema);
}
return nodeCopy;
}
var nodesSupportDragLayoutColumnInto = ['tableCell', 'tableHeader', 'panel', 'expand', 'nestedExpand'];
var isDragLayoutColumnIntoSupportedNodes = function isDragLayoutColumnIntoSupportedNodes($from, $to) {
var _$from$nodeAfter;
var isTopLevel = $to.depth === 0;
var isDragIntoNodes = nodesSupportDragLayoutColumnInto.includes($to.parent.type.name);
var supportedCondition = isDragIntoNodes || isTopLevel;
return ((_$from$nodeAfter = $from.nodeAfter) === null || _$from$nodeAfter === void 0 ? void 0 : _$from$nodeAfter.type.name) === 'layoutColumn' && $from.parent.type.name === 'layoutSection' && supportedCondition;
};
/**
*
* @returns the start position of a node if the node can be moved, otherwise -1
*/
var getCurrentNodePos = function getCurrentNodePos(state) {
var selection = state.selection;
var currentNodePos = -1;
// There are 3 cases when a node can be moved
var focusedHandle = getFocusedHandle(state);
if (focusedHandle) {
// 1. drag handle of the node is focused
currentNodePos = focusedHandle.pos;
} else if (isInTable(state)) {
if (isTableSelected(selection)) {
var _findTable$pos, _findTable;
// We only move table node if it's fully selected
// to avoid shortcut collision with table drag and drop
currentNodePos = (_findTable$pos = (_findTable = findTable(selection)) === null || _findTable === void 0 ? void 0 : _findTable.pos) !== null && _findTable$pos !== void 0 ? _findTable$pos : currentNodePos;
}
} else if (!(state.selection instanceof GapCursorSelection)) {
// 2. caret cursor is inside the node
// 3. the start of the selection is inside the node
currentNodePos = selection.$from.before(1);
if (selection.$from.depth > 0) {
currentNodePos = getNestedNodePosition({
selection: selection,
schema: state.schema,
resolve: state.doc.resolve.bind(state.doc)
});
}
}
return currentNodePos;
};
var getFocusedHandle = function getFocusedHandle(state) {
var _activeNode$handleOpt;
var _ref = key.getState(state) || {},
activeNode = _ref.activeNode;
return activeNode && (_activeNode$handleOpt = activeNode.handleOptions) !== null && _activeNode$handleOpt !== void 0 && _activeNode$handleOpt.isFocused ? activeNode : undefined;
};
export var moveNodeViaShortcut = function moveNodeViaShortcut(api, direction, formatMessage) {
return function (state) {
var selection = state.selection;
var isParentNodeOfTypeLayout = !!findParentNodeOfType([state.schema.nodes.layoutSection])(state.selection);
var isMultiSelectEnabled = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
var expandedSelection = expandSelectionBounds(selection.$anchor, selection.$head);
var expandedAnchor = expandedSelection.$anchor.pos;
var expandedHead = expandedSelection.$head.pos;
var hoistedPos;
var from = Math.min(expandedAnchor, expandedHead);
// Nodes like lists nest within themselves, we need to find the top most position
if (isParentNodeOfTypeLayout) {
var LAYOUT_COL_DEPTH = 3;
hoistedPos = state.doc.resolve(from).before(LAYOUT_COL_DEPTH);
}
var currentNodePos = isMultiSelectEnabled && !getFocusedHandle(state) && !selection.empty ? hoistedPos !== null && hoistedPos !== void 0 ? hoistedPos : from : getCurrentNodePos(state);
if (currentNodePos > -1) {
var _state$doc$nodeAt;
var $currentNodePos = state.doc.resolve(currentNodePos);
var nodeAfterPos = isMultiSelectEnabled && !getFocusedHandle(state) ? Math.max(expandedAnchor, expandedHead) : $currentNodePos.posAtIndex($currentNodePos.index() + 1);
var isTopLevelNode = $currentNodePos.depth === 0;
var moveToPos = -1;
var isLayoutColumnSelected = selection instanceof NodeSelection && selection.node.type.name === 'layoutColumn';
if (direction === DIRECTION.LEFT) {
if (isTopLevelNode && editorExperiment('advanced_layouts', true)) {
var _api$core, _api$core2;
var nodeBefore = $currentNodePos.nodeBefore;
if (nodeBefore) {
moveToPos = currentNodePos - nodeBefore.nodeSize;
}
if (moveToPos < 0) {
return false;
}
api === null || api === void 0 || (_api$core = api.core) === null || _api$core === void 0 || _api$core.actions.execute(function (_ref2) {
var _api$blockControls;
var tr = _ref2.tr;
api === null || api === void 0 || (_api$blockControls = api.blockControls) === null || _api$blockControls === void 0 || (_api$blockControls = _api$blockControls.commands) === null || _api$blockControls === void 0 || _api$blockControls.moveToLayout(currentNodePos, moveToPos, {
moveToEnd: true,
moveNodeAtCursorPos: true
})({
tr: tr
});
var insertColumnStep = getInsertLayoutStep(tr);
var mappedTo = insertColumnStep === null || insertColumnStep === void 0 ? void 0 : insertColumnStep.from;
updateSelection(tr, mappedTo, true);
return tr;
});
api === null || api === void 0 || (_api$core2 = api.core) === null || _api$core2 === void 0 || _api$core2.actions.focus();
return true;
} else if (isLayoutColumnSelected) {
var _$currentNodePos$node, _api$core3, _api$blockControls2;
moveToPos = selection.from - (((_$currentNodePos$node = $currentNodePos.nodeBefore) === null || _$currentNodePos$node === void 0 ? void 0 : _$currentNodePos$node.nodeSize) || 1);
api === null || api === void 0 || (_api$core3 = api.core) === null || _api$core3 === void 0 || _api$core3.actions.execute(api === null || api === void 0 || (_api$blockControls2 = api.blockControls) === null || _api$blockControls2 === void 0 || (_api$blockControls2 = _api$blockControls2.commands) === null || _api$blockControls2 === void 0 ? void 0 : _api$blockControls2.moveToLayout(currentNodePos, moveToPos, {
selectMovedNode: true
}));
return true;
} else {
if ($currentNodePos.depth < 2 || !isParentNodeOfTypeLayout) {
return false;
}
// get the previous layoutSection node
var index = $currentNodePos.index($currentNodePos.depth - 1);
var grandParent = $currentNodePos.node($currentNodePos.depth - 1);
var previousNode = grandParent ? grandParent.maybeChild(index - 1) : null;
moveToPos = $currentNodePos.start() - ((previousNode === null || previousNode === void 0 ? void 0 : previousNode.nodeSize) || 1);
}
} else if (direction === DIRECTION.RIGHT) {
if (isTopLevelNode && editorExperiment('advanced_layouts', true)) {
var _api$core4, _api$core5;
var endOfDoc = $currentNodePos.end();
moveToPos = $currentNodePos.posAtIndex($currentNodePos.index() + 1);
if (moveToPos >= endOfDoc) {
return false;
}
api === null || api === void 0 || (_api$core4 = api.core) === null || _api$core4 === void 0 || _api$core4.actions.execute(function (_ref3) {
var _api$blockControls3;
var tr = _ref3.tr;
api === null || api === void 0 || (_api$blockControls3 = api.blockControls) === null || _api$blockControls3 === void 0 || (_api$blockControls3 = _api$blockControls3.commands) === null || _api$blockControls3 === void 0 || _api$blockControls3.moveToLayout(currentNodePos, moveToPos, {
moveNodeAtCursorPos: true
})({
tr: tr
});
var insertColumnStep = getInsertLayoutStep(tr);
var mappedTo = insertColumnStep === null || insertColumnStep === void 0 ? void 0 : insertColumnStep.from;
updateSelection(tr, mappedTo);
return tr;
});
api === null || api === void 0 || (_api$core5 = api.core) === null || _api$core5 === void 0 || _api$core5.actions.focus();
return true;
} else if (isLayoutColumnSelected) {
var _api$core6, _api$blockControls4;
var _index = $currentNodePos.index($currentNodePos.depth);
var parent = $currentNodePos.node($currentNodePos.depth);
// get the next layoutColumn node
var nextNode = parent ? parent.maybeChild(_index + 1) : null;
// if the current node is the last node, don't do anything
if (_index >= parent.childCount - 1) {
// prevent event propagation to avoid moving the cursor and still select the node
return true;
}
var moveToEnd = _index === parent.childCount - 2;
moveToPos = moveToEnd ? $currentNodePos.before() : selection.to + ((nextNode === null || nextNode === void 0 ? void 0 : nextNode.nodeSize) || 1);
api === null || api === void 0 || (_api$core6 = api.core) === null || _api$core6 === void 0 || _api$core6.actions.execute(api === null || api === void 0 || (_api$blockControls4 = api.blockControls) === null || _api$blockControls4 === void 0 || (_api$blockControls4 = _api$blockControls4.commands) === null || _api$blockControls4 === void 0 ? void 0 : _api$blockControls4.moveToLayout(currentNodePos, moveToPos, {
moveToEnd: moveToEnd,
selectMovedNode: true
}));
return true;
} else {
if ($currentNodePos.depth < 2 || !isParentNodeOfTypeLayout) {
return false;
}
moveToPos = $currentNodePos.after($currentNodePos.depth) + 1;
}
} else if (direction === DIRECTION.UP) {
if (isLayoutColumnSelected) {
moveToPos = $currentNodePos.start() - 1;
} else {
moveToPos = getPosWhenMoveNodeUp($currentNodePos, currentNodePos);
}
} else {
var _endOfDoc = $currentNodePos.end();
if (nodeAfterPos > _endOfDoc) {
return false;
}
if (isLayoutColumnSelected) {
moveToPos = state.selection.$from.end() + 1;
} else {
moveToPos = getPosWhenMoveNodeDown({
$currentNodePos: $currentNodePos,
nodeAfterPos: nodeAfterPos,
tr: state.tr
});
}
}
var nodeType = (_state$doc$nodeAt = state.doc.nodeAt(currentNodePos)) === null || _state$doc$nodeAt === void 0 ? void 0 : _state$doc$nodeAt.type.name;
var shouldMoveNode = false;
if (moveToPos > -1) {
var isDestDepthSameAsSource = $currentNodePos.depth === state.doc.resolve(moveToPos).depth;
var isSourceLayoutColumn = nodeType === 'layoutColumn';
shouldMoveNode = isDestDepthSameAsSource || isSourceLayoutColumn;
}
var _expandSelectionBound = expandSelectionBounds($currentNodePos, selection.$to),
$newAnchor = _expandSelectionBound.$anchor,
$newHead = _expandSelectionBound.$head;
if (shouldMoveNode) {
var _api$core7;
api === null || api === void 0 || (_api$core7 = api.core) === null || _api$core7 === void 0 || _api$core7.actions.execute(function (_ref4) {
var tr = _ref4.tr;
api === null || api === void 0 || api.blockControls.commands.setMultiSelectPositions($newAnchor.pos, $newHead.pos)({
tr: tr
});
moveNode(api)(currentNodePos, moveToPos, INPUT_METHOD.SHORTCUT, formatMessage)({
tr: tr
});
tr.scrollIntoView();
return tr;
});
return true;
} else if (nodeType && !isMultiSelectEnabled) {
var _api$core8;
// If the node is first/last one, only select the node
api === null || api === void 0 || (_api$core8 = api.core) === null || _api$core8 === void 0 || _api$core8.actions.execute(function (_ref5) {
var tr = _ref5.tr;
selectNode(tr, currentNodePos, nodeType, api);
tr.scrollIntoView();
return tr;
});
return true;
} else if (isMultiSelectEnabled) {
var _api$core9;
api === null || api === void 0 || (_api$core9 = api.core) === null || _api$core9 === void 0 || _api$core9.actions.execute(function (_ref6) {
var tr = _ref6.tr;
api === null || api === void 0 || api.blockControls.commands.setMultiSelectPositions($newAnchor.pos, $newHead.pos)({
tr: tr
});
tr.scrollIntoView();
return tr;
});
return true;
}
}
return false;
};
};
export var moveNode = function moveNode(api) {
return function (start, to) {
var inputMethod = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : INPUT_METHOD.DRAG_AND_DROP;
var formatMessage = arguments.length > 3 ? arguments[3] : undefined;
return function (_ref7) {
var _api$blockControls$sh, _convertedNodeSlice, _api$accessibilityUti;
var tr = _ref7.tr;
if (!api || start < 0 || to < 0) {
return tr;
}
var handleNode = tr.doc.nodeAt(start);
if (!handleNode) {
return tr;
}
var sliceFrom = start;
var sliceTo;
var sourceNodeTypes, hasSelectedMultipleNodes;
var isMultiSelect = editorExperiment('platform_editor_element_drag_and_drop_multiselect', true);
if (fg('platform_editor_ease_of_use_metrics')) {
var _api$metrics;
api === null || api === void 0 || (_api$metrics = api.metrics) === null || _api$metrics === void 0 || _api$metrics.commands.setContentMoved()({
tr: tr
});
}
var preservedSelection = editorExperiment('platform_editor_block_menu', true) ? api === null || api === void 0 || (_api$blockControls$sh = api.blockControls.sharedState.currentState()) === null || _api$blockControls$sh === void 0 ? void 0 : _api$blockControls$sh.preservedSelection : undefined;
if (preservedSelection) {
var $from = tr.doc.resolve(Math.min(start, preservedSelection.from));
var expandedRange = $from.blockRange(preservedSelection.$to);
sliceFrom = expandedRange ? expandedRange.start : preservedSelection.from;
sliceTo = expandedRange ? expandedRange.end : preservedSelection.to;
var attributes = getMultiSelectAnalyticsAttributes(tr, sliceFrom, sliceTo);
hasSelectedMultipleNodes = attributes.hasSelectedMultipleNodes;
sourceNodeTypes = attributes.nodeTypes;
} else if (isMultiSelect) {
var slicePosition = getSelectedSlicePosition(start, tr, api);
sliceFrom = slicePosition.from;
sliceTo = slicePosition.to;
var _attributes = getMultiSelectAnalyticsAttributes(tr, sliceFrom, sliceTo);
hasSelectedMultipleNodes = _attributes.hasSelectedMultipleNodes;
sourceNodeTypes = _attributes.nodeTypes;
} else {
var _handleNode$nodeSize;
var size = (_handleNode$nodeSize = handleNode === null || handleNode === void 0 ? void 0 : handleNode.nodeSize) !== null && _handleNode$nodeSize !== void 0 ? _handleNode$nodeSize : 1;
sliceTo = sliceFrom + size;
}
var _tr$doc$type$schema$n = tr.doc.type.schema.nodes,
expand = _tr$doc$type$schema$n.expand,
nestedExpand = _tr$doc$type$schema$n.nestedExpand;
var $to = tr.doc.resolve(to);
var $handlePos = tr.doc.resolve(start);
var nodeCopy = tr.doc.slice(sliceFrom, sliceTo, false); // cut the content
var destNode = $to.node();
var destType = destNode.type;
var destParent = $to.node($to.depth);
var sourceNode = $handlePos.nodeAfter;
//TODO: ED-26959 - Does this need to be updated with new selection logic above? ^
// Move a layout column to top level, or table cell, or panel, or expand, only moves the content into them
if (sourceNode && isDragLayoutColumnIntoSupportedNodes($handlePos, $to)) {
// need update after we support single column layout.
var layoutColumnContent = sourceNode.content;
var fragment;
// if drop into table, and layout column contains expand, transform it to nestedExpand
if (['tableCell', 'tableHeader'].includes($to.parent.type.name)) {
var contentContainsExpand = findChildrenByType(sourceNode, expand).length > 0;
fragment = contentContainsExpand ? transformFragmentExpandToNestedExpand(Fragment.from(layoutColumnContent)) : Fragment.from(layoutColumnContent);
if (!fragment) {
return tr;
}
} else {
fragment = Fragment.from(layoutColumnContent);
}
removeFromSource(tr, $handlePos, $handlePos.pos + sourceNode.nodeSize);
var _mappedTo = tr.mapping.map(to);
tr.insert(_mappedTo, fragment).setSelection(Selection.near(tr.doc.resolve(_mappedTo))).scrollIntoView();
return tr;
}
if (!canMoveNodeToIndex(destParent, $to.index(), $handlePos.node().child($handlePos.index()), $to)) {
return tr;
}
var convertedNodeSlice = transformSourceSlice(nodeCopy, destType);
var convertedNode = (_convertedNodeSlice = convertedNodeSlice) === null || _convertedNodeSlice === void 0 ? void 0 : _convertedNodeSlice.content;
if (!convertedNode) {
return tr;
}
// Currently we don't support breakout mark for children nodes of bodiedSyncBlock node
// Hence strip out the mark for now
if (destNode.type.name === 'bodiedSyncBlock' && editorExperiment('platform_synced_block', true)) {
var _convertedNodeSlice2;
var nodes = [];
(_convertedNodeSlice2 = convertedNodeSlice) === null || _convertedNodeSlice2 === void 0 || _convertedNodeSlice2.content.forEach(function (node) {
nodes.push(node.mark(node.marks.filter(function (mark) {
return mark.type.name !== 'breakout';
})));
});
convertedNodeSlice = new Slice(Fragment.from(nodes), 0, 0);
convertedNode = convertedNodeSlice.content;
}
// delete the content from the original position
tr.delete(sliceFrom, sliceTo);
var mappedTo = tr.mapping.map(to);
var isDestNestedLoneEmptyParagraph = destParent.type.name !== 'doc' && destParent.childCount === 1 && isEmptyParagraph($to.nodeAfter);
if (convertedNodeSlice && isDestNestedLoneEmptyParagraph) {
// if only a single empty paragraph within container, replace it
tr.replace(mappedTo, mappedTo + 1, convertedNodeSlice);
} else {
// otherwise just insert the content at the new position
tr.insert(mappedTo, convertedNode);
}
var sliceSize = sliceTo - sliceFrom;
if (inputMethod === INPUT_METHOD.DRAG_AND_DROP) {
tr = setCursorPositionAtMovedNode(tr, mappedTo, api);
} else if (preservedSelection) {
var _currMeta = tr.getMeta(key);
var nodeMovedOffset = mappedTo - sliceFrom;
tr.setMeta(key, _objectSpread(_objectSpread({}, _currMeta), {}, {
preservedSelectionMapping: new Mapping([new StepMap([0, 0, nodeMovedOffset])])
}));
} else if (isMultiSelect) {
var _api$blockControls$co;
tr = (_api$blockControls$co = api === null || api === void 0 ? void 0 : api.blockControls.commands.setMultiSelectPositions(mappedTo, mappedTo + sliceSize)({
tr: tr
})) !== null && _api$blockControls$co !== void 0 ? _api$blockControls$co : tr;
} else {
tr = selectNode(tr, mappedTo, handleNode.type.name, api);
}
var currMeta = tr.getMeta(key);
tr.setMeta(key, _objectSpread(_objectSpread({}, currMeta), {}, {
nodeMoved: true
}));
if (
// when move node via block menu, we need to keep the focus on block menu popup, so don't move focus to editor in this scenario
!(inputMethod === INPUT_METHOD.BLOCK_MENU && editorExperiment('platform_editor_block_menu', true))) {
api === null || api === void 0 || api.core.actions.focus();
}
var $mappedTo = tr.doc.resolve(mappedTo);
var expandAncestor = findParentNodeOfTypeClosestToPos($to, [expand, nestedExpand]);
if (expandAncestor) {
var wasExpandExpanded = expandedState.get(expandAncestor.node);
var updatedExpandAncestor = findParentNodeOfTypeClosestToPos($mappedTo, [expand, nestedExpand]);
if (wasExpandExpanded !== undefined && updatedExpandAncestor) {
expandedState.set(updatedExpandAncestor.node, wasExpandExpanded);
}
}
if (editorExperiment('advanced_layouts', true)) {
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);
} else {
var _api$analytics;
api === null || api === void 0 || (_api$analytics = api.analytics) === null || _api$analytics === void 0 || _api$analytics.actions.attachAnalyticsEvent({
eventType: EVENT_TYPE.TRACK,
action: ACTION.MOVED,
actionSubject: ACTION_SUBJECT.ELEMENT,
actionSubjectId: ACTION_SUBJECT_ID.ELEMENT_DRAG_HANDLE,
attributes: _objectSpread({
nodeDepth: $handlePos.depth,
nodeType: handleNode.type.name,
destinationNodeDepth: $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.depth,
destinationNodeType: $mappedTo === null || $mappedTo === void 0 ? void 0 : $mappedTo.parent.type.name,
inputMethod: inputMethod
}, isMultiSelect && {
sourceNodeTypes: sourceNodeTypes,
hasSelectedMultipleNodes: hasSelectedMultipleNodes
})
})(tr);
}
var movedMessage = to > sliceFrom ? blockControlsMessages.movedDown : blockControlsMessages.movedup;
api === null || api === void 0 || (_api$accessibilityUti = api.accessibilityUtils) === null || _api$accessibilityUti === void 0 || _api$accessibilityUti.actions.ariaNotify(formatMessage ? formatMessage(movedMessage) : movedMessage.defaultMessage, {
priority: 'important'
});
return tr;
};
};
};