@atlaskit/editor-core
Version:
A package contains Atlassian editor core functionality
104 lines • 5.05 kB
JavaScript
import { keymap, TextSelection, } from '../../prosemirror';
import uuid from './uuid';
export function keymapPlugin(schema) {
var deleteCurrentItem = function ($from, tr) {
return tr.delete($from.before($from.depth) - 1, $from.end($from.depth) + 1);
};
var deleteList = function ($from, tr, content) {
return tr.replaceWith($from.start($from.depth - 1) - 1, $from.end($from.depth - 1) + 1, content);
};
/*
* Since the DecisionItem and TaskItem only accepts inline-content, we won't get any of the default behaviour from ProseMirror
* eg. behaviour for backspace and enter etc. So we need to implement it.
*/
var keymaps = {
'Backspace': function (state, dispatch) {
var selection = state.selection, nodes = state.schema.nodes, tr = state.tr;
var decisionList = nodes.decisionList, decisionItem = nodes.decisionItem, taskList = nodes.taskList, taskItem = nodes.taskItem;
if ((!decisionItem || !decisionList) && (!taskList || !taskItem)) {
return false;
}
var $from = selection.$from, $to = selection.$to;
// Don't do anything if selection is a range
if ($from.pos !== $to.pos) {
return false;
}
var nodeType = $from.node($from.depth).type;
var isFirstItemInList = (nodeType === decisionItem || nodeType === taskItem) && $from.index($from.depth - 1) === 0;
// Don't do anything if the cursor isn't at the begining of the node.
if ($from.parentOffset !== 0) {
return false;
}
if ($from.depth !== 1 && !isFirstItemInList) {
return false;
}
var previousPos = tr.doc.resolve(Math.max(0, $from.before(1) - 1));
if (previousPos.pos === 0 && !isFirstItemInList) {
return false;
}
var previousNodeType = previousPos.pos > 0 && previousPos.node(1).type;
var parentNodeType = $from.node(1).type;
var previousNodeIsList = (previousNodeType === decisionList || previousNodeType === taskList);
var parentNodeIsList = (parentNodeType === decisionList || parentNodeType === taskList);
if (previousNodeIsList && !parentNodeIsList) {
var content = $from.node($from.depth).content;
deleteCurrentItem($from, tr)
.insert(previousPos.pos - 1, content)
.setSelection(new TextSelection(tr.doc.resolve(previousPos.pos - 1)))
.scrollIntoView();
dispatch(tr);
return true;
}
else if (isFirstItemInList) {
var content = schema.nodes.paragraph.create({}, $from.node($from.depth).content);
var insertPos = previousPos.pos > 0 ? previousPos.pos + 1 : 0;
var isOnlyChild = $from.node($from.depth - 1).childCount === 1;
if (!isOnlyChild) {
deleteCurrentItem($from, tr).insert(insertPos, content);
}
else {
deleteList($from, tr, content);
}
tr
.setSelection(new TextSelection(tr.doc.resolve(insertPos + 1)))
.scrollIntoView();
dispatch(tr);
return true;
}
},
'Enter': function (state, dispatch) {
var selection = state.selection, tr = state.tr, nodes = state.schema.nodes;
var $from = selection.$from;
var node = $from.node($from.depth);
var nodeType = node && node.type;
var nodeIsTaskOrDecisionItem = nodeType === nodes.decisionItem || nodeType === nodes.taskItem;
var isEmpty = node && node.textContent.length === 0;
if (nodeIsTaskOrDecisionItem) {
var list = $from.node($from.depth - 1);
var end = $from.end($from.depth - 1) + 1;
if (!isEmpty) {
tr.split($from.pos, 1, [{ type: nodeType, attrs: { localId: uuid.generate() } }]);
dispatch(tr);
return true;
}
// If list is empty, replace with paragraph
if (isEmpty && list.childCount === 1) {
deleteList($from, tr, schema.nodes.paragraph.create({}));
dispatch(tr);
return true;
}
// If last child, remove it and insert a paragraph
if (isEmpty && list.child(list.childCount - 1) === node) {
tr.insert(end, schema.nodes.paragraph.create({}));
deleteCurrentItem($from, tr);
dispatch(tr);
return true;
}
}
return false;
}
};
return keymap(keymaps);
}
export default keymapPlugin;
//# sourceMappingURL=keymaps.js.map