@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
96 lines (93 loc) • 3.37 kB
JavaScript
import { Selection } from '@atlaskit/editor-prosemirror/state';
import { GapCursorSelection, Side } from './selection';
import { isValidTargetNode } from './utils/is-valid-target-node';
// This function captures clicks outside of the ProseMirror contentEditable area
// see also description of "handleClick" in gap-cursor pm-plugin
var captureCursorCoords = function captureCursorCoords(event, editorRef, posAtCoords, tr
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/max-params
) {
var rect = editorRef.getBoundingClientRect();
// capture clicks before the first block element
if (event.clientY < rect.top) {
return {
position: 0,
side: Side.LEFT
};
}
if (rect.left > 0) {
// calculate start position of a node that is vertically at the same level
var coords = posAtCoords({
left: rect.left,
top: event.clientY
});
if (coords && coords.inside > -1) {
var $from = tr.doc.resolve(coords.inside);
var start = $from.before(1);
var side = event.clientX < rect.left ? Side.LEFT : Side.RIGHT;
var position;
if (side === Side.LEFT) {
position = start;
} else {
var node = tr.doc.nodeAt(start);
if (node) {
position = start + node.nodeSize;
}
}
return {
position: position,
side: side
};
}
}
return null;
};
export var setSelectionTopLevelBlocks = function setSelectionTopLevelBlocks(tr, event, editorRef, posAtCoords, editorFocused
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/max-params
) {
var cursorCoords = captureCursorCoords(event, editorRef, posAtCoords, tr);
if (!cursorCoords) {
return;
}
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
var $pos = cursorCoords.position !== undefined ? tr.doc.resolve(cursorCoords.position) : null;
if ($pos === null) {
return;
}
var isGapCursorAllowed = cursorCoords.side === Side.LEFT ? isValidTargetNode($pos.nodeAfter) : isValidTargetNode($pos.nodeBefore);
if (isGapCursorAllowed && GapCursorSelection.valid($pos)) {
// this forces PM to re-render the decoration node if we change the side of the gap cursor, it doesn't do it by default
if (tr.selection instanceof GapCursorSelection) {
tr.setSelection(Selection.near($pos));
} else {
tr.setSelection(new GapCursorSelection($pos, cursorCoords.side));
}
}
// try to set text selection if the editor isnt focused
// if the editor is focused, we are most likely dragging a selection outside.
else if (editorFocused === false) {
var selectionTemp = Selection.findFrom($pos, cursorCoords.side === Side.LEFT ? 1 : -1, true);
if (selectionTemp) {
tr.setSelection(selectionTemp);
}
}
};
export var setGapCursorAtPos = function setGapCursorAtPos(position) {
var side = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : Side.LEFT;
return function (state, dispatch) {
// @see ED-6231
if (position > state.doc.content.size) {
return false;
}
var $pos = state.doc.resolve(position);
if (GapCursorSelection.valid($pos)) {
if (dispatch) {
dispatch(state.tr.setSelection(new GapCursorSelection($pos, side)));
}
return true;
}
return false;
};
};