UNPKG

@atlaskit/editor-plugin-block-controls

Version:

Block controls plugin for @atlaskit/editor-core

117 lines (113 loc) 5.1 kB
import { NodeSelection } from '@atlaskit/editor-prosemirror/state'; import { findTable, isTableSelected } from '@atlaskit/editor-tables/utils'; import { editorExperiment } from '@atlaskit/tmp-editor-statsig/experiments'; import { createPreservedSelection } from '../../pm-plugins/utils/selection'; /** * Gets the current node position and bounds from the selection using the preserved selection logic. * This ensures consistency with how the block controls plugin handles selection boundaries. * * Special handling for tables: When moving a table as a block, we need the outer table node's * position, not the internal cell selection that createPreservedSelection returns. * * @param selection The current editor selection * @returns An object with from and to positions, or undefined if selection is invalid */ export var getNodeBoundsFromSelection = function getNodeBoundsFromSelection(selection) { // Special case: if a table is selected, we want to move the entire table node var tableInfo = findTable(selection); if (tableInfo && isTableSelected(selection)) { var tablePos = tableInfo.pos; var tableTo = tablePos + tableInfo.node.nodeSize; return { from: tablePos, to: tableTo }; } // Special case: if a media node (file) is selected, we need to get the parent mediaGroup // This handles the case where clicking on a file creates a NodeSelection of the media node // but we want to move the entire mediaGroup that wraps it if (selection instanceof NodeSelection && selection.node.type.name === 'media' && selection.node.attrs.type === 'file' && editorExperiment('platform_editor_block_menu', true)) { // The media node is wrapped in a mediaGroup, so we need to get the parent position var mediaGroupPos = selection.$from.pos - 1; var mediaGroupNode = selection.$from.doc.nodeAt(mediaGroupPos); if (mediaGroupNode && mediaGroupNode.type.name === 'mediaGroup') { return { from: mediaGroupPos, to: mediaGroupPos + mediaGroupNode.nodeSize }; } } // Use createPreservedSelection to get properly expanded block boundaries var preservedSelection = createPreservedSelection(selection.$from, selection.$to); if (!preservedSelection) { return undefined; } return { from: preservedSelection.from, to: preservedSelection.to }; }; export var getPosWhenMoveNodeUp = function getPosWhenMoveNodeUp($currentNodePos, currentNodePos) { var nodeIndex = $currentNodePos.index(); var nodeBefore = $currentNodePos.depth > 1 && nodeIndex === 0 ? $currentNodePos.node($currentNodePos.depth) : $currentNodePos.nodeBefore; if ((nodeBefore === null || nodeBefore === void 0 ? void 0 : nodeBefore.type.name) === 'layoutColumn' && editorExperiment('platform_editor_block_menu', true)) { return -1; } return nodeBefore ? currentNodePos - nodeBefore.nodeSize : -1; }; export var getPosWhenMoveNodeDown = function getPosWhenMoveNodeDown(_ref) { var $currentNodePos = _ref.$currentNodePos, nodeAfterPos = _ref.nodeAfterPos, tr = _ref.tr; var endOfDoc = $currentNodePos.end(); if (nodeAfterPos > endOfDoc) { return -1; } var nodeAfter = tr.doc.nodeAt(nodeAfterPos); if (editorExperiment('platform_editor_block_menu', true)) { var nodeAtCurrentPos = tr.doc.nodeAt($currentNodePos.pos); // if move empty line down to another empty line, move to the position of the next empty line if ((nodeAtCurrentPos === null || nodeAtCurrentPos === void 0 ? void 0 : nodeAtCurrentPos.content.size) === 0 && nodeAtCurrentPos.type.name !== 'extension' && (nodeAfter === null || nodeAfter === void 0 ? void 0 : nodeAfter.content.size) === 0 && nodeAfter.type.name !== 'extension') { return nodeAfterPos; } } // if not the last node, move to the end of the next node return nodeAfter ? nodeAfterPos + nodeAfter.nodeSize : -1; }; export var getShouldMoveNode = function getShouldMoveNode(_ref2) { var currentNodePos = _ref2.currentNodePos, moveToPos = _ref2.moveToPos, tr = _ref2.tr; // only move the node if the destination is at the same depth, not support moving a nested node to a parent node return moveToPos > -1 && tr.doc.resolve(currentNodePos).depth === tr.doc.resolve(moveToPos).depth; }; export var canMoveNodeUpOrDown = function canMoveNodeUpOrDown(tr) { var nodeBounds = getNodeBoundsFromSelection(tr.selection); if (!nodeBounds || nodeBounds.from <= -1) { return { moveUp: false, moveDown: false }; } var currentNodePos = nodeBounds.from; var $currentNodePos = tr.doc.resolve(currentNodePos); var nodeAfterPos = nodeBounds.to; var moveUpPos = getPosWhenMoveNodeUp($currentNodePos, currentNodePos); var moveDownPos = getPosWhenMoveNodeDown({ $currentNodePos: $currentNodePos, nodeAfterPos: nodeAfterPos, tr: tr }); return { moveUp: getShouldMoveNode({ currentNodePos: currentNodePos, moveToPos: moveUpPos, tr: tr }), moveDown: getShouldMoveNode({ currentNodePos: currentNodePos, moveToPos: moveDownPos, tr: tr }) }; };