UNPKG

@atlaskit/editor-plugin-tasks-and-decisions

Version:

Tasks and decisions plugin for @atlaskit/editor-core

96 lines (95 loc) 2.72 kB
import { buildReplacementFragment, computeSelectionOffsets, narrowReplacementRange, restoreSelection } from '@atlaskit/editor-common/lists'; import { findFarthestParentNode } from '@atlaskit/editor-common/utils'; import { flattenTaskList, rebuildTaskList } from '../task-list-indentation'; const MAX_TASK_LIST_DEPTH = 6; export function moveSelectedTaskListItems(tr, indentDelta) { const { doc, selection } = tr; const { schema } = doc.type; const { taskList } = schema.nodes; const { $from, $to } = selection; const rootListResult = findFarthestParentNode(node => node.type === taskList)($from); if (!rootListResult) { return null; } const rootListStart = rootListResult.pos; const rootListEnd = rootListStart + rootListResult.node.nodeSize; const flattenResult = flattenTaskList({ doc, rootListStart, rootListEnd, selectionFrom: $from.pos, selectionTo: $to.pos, indentDelta, maxDepth: MAX_TASK_LIST_DEPTH }); if (!flattenResult) { return null; } const { items: flattenedItems, startIndex, endIndex } = flattenResult; const { fragment, contentStartOffsets } = buildReplacementFragment({ items: flattenedItems, schema, rebuildFn: rebuildTaskList, extractContentFn: (item, s) => { // Extract task item content for breakout. // taskItem has inline content, so wrap in a paragraph. // blockTaskItem already has paragraph children. const { blockTaskItem } = s.nodes; if (!!blockTaskItem && item.node.type === blockTaskItem) { // blockTaskItem children are already paragraphs/extensions const children = []; item.node.forEach(child => children.push(child)); return children; } // Regular taskItem — wrap inline content in a paragraph return [s.nodes.paragraph.create(null, item.node.content)]; } }); if (fragment.size === 0) { return null; } // Narrow the replacement to the minimal changed range for collab-friendly // cursor preservation on unaffected list items. const narrowed = narrowReplacementRange(tr.doc, rootListStart, rootListEnd, fragment, contentStartOffsets); tr.replaceWith(narrowed.start, narrowed.end, narrowed.fragment); const { from, to } = computeSelectionOffsets({ items: flattenedItems, startIndex, endIndex, originalFrom: $from.pos, originalTo: $to.pos, contentStartOffsets: narrowed.adjustedContentStartOffsets, rootListStart: narrowed.start, docSize: tr.doc.content.size }); restoreSelection({ tr, originalSelection: selection, from, to }); tr.scrollIntoView(); return tr; }