@atlaskit/editor-plugin-block-controls
Version:
Block controls plugin for @atlaskit/editor-core
117 lines (113 loc) • 5.1 kB
JavaScript
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
})
};
};