]> BookStack Code Mirror - bookstack/blobdiff - resources/js/wysiwyg/utils/lists.ts
Lexical: Adjusted handling of child/sibling list items on nesting
[bookstack] / resources / js / wysiwyg / utils / lists.ts
index 646f341c2ba3d436b2d105f4c247f8a00a8e5846..005b05f98167aa97b5998e47263ace9ec14a6382 100644 (file)
@@ -1,4 +1,4 @@
-import {$getSelection, BaseSelection, LexicalEditor} from "lexical";
+import {$createTextNode, $getSelection, BaseSelection, LexicalEditor, TextNode} from "lexical";
 import {$getBlockElementNodesInSelection, $selectNodes, $toggleSelection} from "./selection";
 import {nodeHasInset} from "./nodes";
 import {$createListItemNode, $createListNode, $isListItemNode, $isListNode, ListItemNode} from "@lexical/list";
@@ -10,6 +10,9 @@ export function $nestListItem(node: ListItemNode): ListItemNode {
         return node;
     }
 
+    const nodeChildList = node.getChildren().filter(n => $isListNode(n))[0] || null;
+    const nodeChildItems = nodeChildList?.getChildren() || [];
+
     const listItems = list.getChildren() as ListItemNode[];
     const nodeIndex = listItems.findIndex((n) => n.getKey() === node.getKey());
     const isFirst = nodeIndex === 0;
@@ -27,6 +30,13 @@ export function $nestListItem(node: ListItemNode): ListItemNode {
         node.remove();
     }
 
+    if (nodeChildList) {
+        for (const child of nodeChildItems) {
+            newListItem.insertAfter(child);
+        }
+        nodeChildList.remove();
+    }
+
     return newListItem;
 }
 
@@ -38,6 +48,8 @@ export function $unnestListItem(node: ListItemNode): ListItemNode {
         return node;
     }
 
+    const laterSiblings = node.getNextSiblings();
+
     parentListItem.insertAfter(node);
     if (list.getChildren().length === 0) {
         list.remove();
@@ -47,6 +59,16 @@ export function $unnestListItem(node: ListItemNode): ListItemNode {
         parentListItem.remove();
     }
 
+    if (laterSiblings.length > 0) {
+        const childList = $createListNode(list.getListType());
+        childList.append(...laterSiblings);
+        node.append(childList);
+    }
+
+    if (list.getChildrenSize() === 0) {
+        list.remove();
+    }
+
     return node;
 }
 
@@ -93,6 +115,7 @@ function $reduceDedupeListItems(listItems: (ListItemNode|null)[]): ListItemNode[
 
 export function $setInsetForSelection(editor: LexicalEditor, change: number): void {
     const selection = $getSelection();
+    const selectionBounds = selection?.getStartEndPoints();
     const listItemsInSelection = getListItemsForSelection(selection);
     const isListSelection = listItemsInSelection.length > 0 && !listItemsInSelection.includes(null);
 
@@ -110,7 +133,19 @@ export function $setInsetForSelection(editor: LexicalEditor, change: number): vo
             alteredListItems.reverse();
         }
 
-        $selectNodes(alteredListItems);
+        if (alteredListItems.length === 1 && selectionBounds) {
+            // Retain selection range if moving just one item
+            const listItem = alteredListItems[0] as ListItemNode;
+            let child = listItem.getChildren()[0] as TextNode;
+            if (!child) {
+                child = $createTextNode('');
+                listItem.append(child);
+            }
+            child.select(selectionBounds[0].offset, selectionBounds[1].offset);
+        } else {
+            $selectNodes(alteredListItems);
+        }
+
         return;
     }