@atlaskit/editor-plugin-selection
Version:
Selection plugin for @atlaskit/editor-core
115 lines (110 loc) • 4.42 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.onCreateSelectionBetween = void 0;
var _state = require("@atlaskit/editor-prosemirror/state");
var DOC_START_POS = 0;
function isNodeContentEmpty(maybeNode) {
return (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.content.size) === 0 || (maybeNode === null || maybeNode === void 0 ? void 0 : maybeNode.textContent) === '';
}
function findEmptySelectableParentNodePosition($pos) {
var doc = $pos.doc;
if ($pos.pos > doc.content.size) {
return null;
}
if (isCurrentNodeAtomOrEmptySelectable($pos)) {
return $pos;
}
if ($pos.nodeBefore !== null) {
return null;
}
if ($pos.depth === 0 && $pos.pos === 0) {
return $pos;
}
var positionLevelUp = $pos.before();
var resolvedPositionLevelUp = doc.resolve(positionLevelUp);
return findEmptySelectableParentNodePosition(resolvedPositionLevelUp);
}
var isCurrentNodeAtomOrEmptySelectable = function isCurrentNodeAtomOrEmptySelectable($pos) {
//ED-20209: Using $resolvedJustBeforeNodePos so that $resolvedJustBeforeNodePos.nodeAfter return the node at $pos.pos even if that is an atomic node
if ($pos.pos === DOC_START_POS) {
return false;
}
var justBeforeNodePos = $pos.pos - 1;
var $resolvedjustBeforePos = $pos.doc.resolve(justBeforeNodePos);
var maybeNode = $resolvedjustBeforePos.nodeAfter;
if (!maybeNode || !maybeNode.isBlock) {
return false;
}
if (maybeNode.isAtom) {
return true;
}
return isNodeContentEmpty(maybeNode) && _state.NodeSelection.isSelectable(maybeNode);
};
function findNextSelectionPosition(_ref) {
var $targetHead = _ref.$targetHead,
$anchor = _ref.$anchor,
doc = _ref.doc;
var direction = $anchor.pos < $targetHead.pos ? 'down' : 'up';
//ED-20209: If the targetHead position is just before some node, Then return $targetHead and not select any node.
var maybeNode = null;
// prosemirror calls 'createSelectionBetween' for native 'drop' events, it passes $anchor
// and $head which are based on a transformed document, but only provides the original
// doc. Need to remap the $head pos to last element in doc to avoid RangeErrors.
if ($targetHead.pos >= doc.nodeSize) {
maybeNode = doc.resolve(doc.nodeSize - 2).nodeBefore;
} else if ($targetHead.pos !== DOC_START_POS) {
var justBeforeHeadPos = $targetHead.pos - 1;
var $resolvedJustBeforeHeadPos = doc.resolve(justBeforeHeadPos);
maybeNode = $resolvedJustBeforeHeadPos.nodeAfter;
}
if (maybeNode === null) {
maybeNode = $targetHead.nodeAfter;
if (maybeNode !== null) {
$targetHead = doc.resolve($targetHead.pos + 1);
} else {
return null;
}
}
var maybeNextPosition = findEmptySelectableParentNodePosition($targetHead);
if (maybeNextPosition) {
var justBeforeMaybeNextPos = maybeNextPosition.pos - 1;
if (direction === 'up') {
return doc.resolve(Math.max(justBeforeMaybeNextPos, 0));
} else {
var maybeNextNode = doc.resolve(justBeforeMaybeNextPos).nodeAfter;
if (maybeNextNode) {
return doc.resolve(Math.min(justBeforeMaybeNextPos + maybeNextNode.nodeSize, doc.content.size));
}
}
}
return null;
}
var onCreateSelectionBetween = exports.onCreateSelectionBetween = function onCreateSelectionBetween(view, $anchor, $head) {
var _$head$parent, _$head$parent2;
if ($anchor.pos === $head.pos) {
return null;
}
if ($anchor.depth === $head.depth && $anchor.sameParent($head)) {
return null;
}
// If the head is targeting a paragraph on root, then let ProseMirror handle the text selection
if ($head.depth === 1 && ((_$head$parent = $head.parent) === null || _$head$parent === void 0 ? void 0 : _$head$parent.type.name) === 'paragraph') {
return null;
}
// If head is at the beginning of a non-empty textblock, let ProseMirror handle the text selection
if ((_$head$parent2 = $head.parent) !== null && _$head$parent2 !== void 0 && _$head$parent2.isTextblock && !isNodeContentEmpty($head.parent) && $head.parentOffset === 0) {
return null;
}
var $nextHeadPosition = findNextSelectionPosition({
$targetHead: $head,
$anchor: $anchor,
doc: view.state.doc
});
if (!$nextHeadPosition) {
return null;
}
var forcedTextSelection = _state.TextSelection.create(view.state.doc, $anchor.pos, $nextHeadPosition.pos);
return forcedTextSelection;
};