UNPKG

@atlaskit/editor-core

Version:

A package contains Atlassian editor core functionality

104 lines 5.05 kB
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