UNPKG

@atlaskit/editor-plugin-block-controls

Version:

Block controls plugin for @atlaskit/editor-core

479 lines (470 loc) 26.4 kB
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; }; }; };