@atlaskit/editor-plugin-panel
Version:
Panel plugin for @atlaskit/editor-core.
83 lines (79 loc) • 4.3 kB
JavaScript
import { isEmptyNode } from '@atlaskit/editor-common/utils';
import { keymap } from '@atlaskit/editor-prosemirror/keymap';
import { findParentNodeOfType, hasParentNodeOfType, setTextSelection } from '@atlaskit/editor-prosemirror/utils';
function findParentNode(selection, nodeType) {
var parentPosition = findParentNodeOfType(nodeType)(selection);
if (parentPosition) {
return parentPosition.node;
}
return null;
}
function isInsideAnEmptyNode(selection, nodeType, schema) {
var parentNode = findParentNode(selection, nodeType);
return parentNode && isEmptyNode(schema)(parentNode);
}
// Somewhat broken and subverted: https://product-fabric.atlassian.net/browse/ED-6504
export function keymapPlugin() {
var deleteCurrentItem = function deleteCurrentItem($from, tr) {
return tr.delete($from.before($from.depth) - 1, $from.end($from.depth) + 1);
};
var keymaps = {
Backspace: function Backspace(state, dispatch) {
var _$previousPos$nodeAft, _nodeBeforePanel$type;
var selection = state.selection,
nodes = state.schema.nodes,
tr = state.tr;
var panel = nodes.panel,
blockquote = nodes.blockquote,
orderedList = nodes.orderedList,
bulletList = nodes.bulletList,
mediaSingle = nodes.mediaSingle,
mediaGroup = nodes.mediaGroup,
extension = nodes.extension;
var $from = selection.$from,
$to = selection.$to;
// Don't do anything if selection is a range
if ($from.pos !== $to.pos) {
return false;
}
// If not at the start of a panel, no joining will happen so allow default behaviour (backspacing characters etc..)
if ($from.parentOffset !== 0) {
return false;
}
var $previousPos = tr.doc.resolve(Math.max(0, $from.before($from.depth) - 1));
var previousNodeType = $previousPos.pos > 0 && $previousPos.parent && $previousPos.parent.type;
var parentNodeType = $from.parent.type;
var isPreviousNodeAPanel = previousNodeType === panel;
var isParentNodeAPanel = parentNodeType === panel;
var nodeBeforePanel = $previousPos === null || $previousPos === void 0 ? void 0 : $previousPos.nodeBefore;
var isPreviousNodeMedia = previousNodeType === mediaSingle || previousNodeType === mediaGroup;
var isPreviousNodeAList = previousNodeType === bulletList || previousNodeType === orderedList;
// identifies if new position after backspace is at the start of a non-bodied extension node
var isPreviousPosAtExtension = ((_$previousPos$nodeAft = $previousPos.nodeAfter) === null || _$previousPos$nodeAft === void 0 ? void 0 : _$previousPos$nodeAft.type) === extension;
// Stops merging panels when deleting empty paragraph in between
// Stops merging blockquotes with panels when deleting from start of blockquote
if (isPreviousNodeAPanel && !isParentNodeAPanel && !isPreviousPosAtExtension || isInsideAnEmptyNode(selection, panel, state.schema) || hasParentNodeOfType(blockquote)(selection) && !isPreviousNodeAList && !isPreviousNodeMedia && !isPreviousPosAtExtension ||
// Lift line of panel content up and out of the panel, when backspacing
// at the start of a panel, if the node before the panel is an 'isolating' node
// (for e.g. a table, or an expand), otherwise the default prosemirror backspace
// behaviour will fallback to 'select node backward' logic because the node
// before is an isolating node.
nodeBeforePanel !== null && nodeBeforePanel !== void 0 && (_nodeBeforePanel$type = nodeBeforePanel.type) !== null && _nodeBeforePanel$type !== void 0 && (_nodeBeforePanel$type = _nodeBeforePanel$type.spec) !== null && _nodeBeforePanel$type !== void 0 && _nodeBeforePanel$type.isolating && hasParentNodeOfType(panel)(selection)) {
var content = $from.node($from.depth).content;
var insertPos = $previousPos.pos;
deleteCurrentItem($from, tr).insert(insertPos, content);
if (dispatch) {
dispatch(setTextSelection(insertPos)(tr).scrollIntoView());
}
return true;
}
var nodeType = $from.node().type;
if (nodeType !== panel) {
return false;
}
return true;
}
};
return keymap(keymaps);
}
export default keymapPlugin;