@atlaskit/editor-core
Version:
A package contains Atlassian editor core functionality
79 lines (62 loc) • 2.4 kB
text/typescript
import { EditorState, Selection, TextSelection, Transaction, EditorView, Schema } from '../../prosemirror';
import uuid from '../../plugins/tasks-and-decisions/uuid';
const getListTypes = (listType: TaskDecisionListType, schema: Schema<any,any>): { list, item } => {
const { decisionList, decisionItem, taskList, taskItem } = schema.nodes;
if (listType === 'taskList') {
return {
list: taskList,
item: taskItem,
};
}
return {
list: decisionList,
item: decisionItem,
};
};
export type TaskDecisionListType = 'taskList' | 'decisionList';
const isSelectionInAList = (listType: TaskDecisionListType, selection: Selection) => {
const fromNode = selection.$from.node(selection.$from.depth - 2);
const endNode = selection.$to.node(selection.$to.depth - 2);
return fromNode && fromNode.type.name === listType
&& endNode && endNode.type.name !== listType;
};
export const changeToTaskDecision = (
view: EditorView,
listType: TaskDecisionListType
): boolean => {
const { state } = view;
const { selection, schema } = state;
const { list, item } = getListTypes(listType, schema);
const { tr } = state;
if (!isSelectionInAList(listType, selection)) {
// Not a list - convert to one.
const created = createListAtSelection(tr, list, item, schema, state);
view.dispatch(tr);
return created;
}
return false;
};
export const createListAtSelection = (tr: Transaction, list: any, item: any, schema: Schema<any, any>, state: EditorState<any>): boolean => {
const { selection: { $from, $to } } = state;
if ($from.parent !== $to.parent) {
// ignore selections across multiple nodes
return false;
}
const { decisionList, taskList } = schema.nodes;
const isAlreadyDecisionTask = $from.parent.type === decisionList || $from.parent.type === taskList;
if (isAlreadyDecisionTask) {
return false;
}
const where = $from.before($from.depth);
const content = $from.node($from.depth).content;
tr
.delete(where, $from.end($from.depth))
.replaceSelectionWith(list.create({ localId: uuid.generate() }, [item.create({}, content)]))
;
// Adjust selection into new item, if not there (e.g. in full page editor)
const newSelection = tr.selection;
if (newSelection.$from.parent.type !== item) {
tr.setSelection(TextSelection.create(tr.doc, newSelection.$from.pos - 2));
}
return true;
};