diff --git a/resources/js/components/page-editor.js b/resources/js/components/page-editor.js
index 64cd601a9..81378e944 100644
--- a/resources/js/components/page-editor.js
+++ b/resources/js/components/page-editor.js
@@ -112,7 +112,7 @@ export class PageEditor extends Component {
     }
 
     savePage() {
-        this.container.closest('form').submit();
+        this.container.closest('form').requestSubmit();
     }
 
     async saveDraft() {
diff --git a/resources/js/components/wysiwyg-editor.js b/resources/js/components/wysiwyg-editor.js
index 56dbe8d7c..5a2581900 100644
--- a/resources/js/components/wysiwyg-editor.js
+++ b/resources/js/components/wysiwyg-editor.js
@@ -25,6 +25,7 @@ export class WysiwygEditor extends Component {
                 textDirection: this.$opts.textDirection,
                 translations,
             });
+            window.wysiwyg = this.editor;
         });
 
         let handlingFormSubmit = false;
@@ -38,7 +39,9 @@ export class WysiwygEditor extends Component {
                 handlingFormSubmit = true;
                 this.editor.getContentAsHtml().then(html => {
                     this.input.value = html;
-                    this.input.form.submit();
+                    setTimeout(() => {
+                        this.input.form.requestSubmit();
+                    }, 5);
                 });
             } else {
                 handlingFormSubmit = false;
diff --git a/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts b/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts
index d54a64ce8..6a8e45724 100644
--- a/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts
+++ b/resources/js/wysiwyg/lexical/core/__tests__/utils/index.ts
@@ -37,6 +37,7 @@ import {QuoteNode} from "@lexical/rich-text/LexicalQuoteNode";
 import {DetailsNode} from "@lexical/rich-text/LexicalDetailsNode";
 import {EditorUiContext} from "../../../../ui/framework/core";
 import {EditorUIManager} from "../../../../ui/framework/manager";
+import {ImageNode} from "@lexical/rich-text/LexicalImageNode";
 
 type TestEnv = {
   readonly container: HTMLDivElement;
@@ -484,6 +485,9 @@ export function createTestContext(): EditorUiContext {
   const editor = createTestEditor({
     namespace: 'testing',
     theme: {},
+    nodes: [
+        ImageNode,
+    ]
   });
 
   editor.setRootElement(editorDOM);
diff --git a/resources/js/wysiwyg/lexical/list/LexicalListNode.ts b/resources/js/wysiwyg/lexical/list/LexicalListNode.ts
index 6edf0d64a..b5c83addd 100644
--- a/resources/js/wysiwyg/lexical/list/LexicalListNode.ts
+++ b/resources/js/wysiwyg/lexical/list/LexicalListNode.ts
@@ -332,7 +332,19 @@ function isDomChecklist(domNode: HTMLElement) {
   }
   // if children are checklist items, the node is a checklist ul. Applicable for googledoc checklist pasting.
   for (const child of domNode.childNodes) {
-    if (isHTMLElement(child) && child.hasAttribute('aria-checked')) {
+    if (!isHTMLElement(child)) {
+      continue;
+    }
+
+    if (child.hasAttribute('aria-checked')) {
+      return true;
+    }
+
+    if (child.classList.contains('task-list-item')) {
+      return true;
+    }
+
+    if (child.firstElementChild && child.firstElementChild.matches('input[type="checkbox"]')) {
       return true;
     }
   }
diff --git a/resources/js/wysiwyg/lexical/list/__tests__/unit/LexicalListNode.test.ts b/resources/js/wysiwyg/lexical/list/__tests__/unit/LexicalListNode.test.ts
index 8c7729dbf..b85383e7d 100644
--- a/resources/js/wysiwyg/lexical/list/__tests__/unit/LexicalListNode.test.ts
+++ b/resources/js/wysiwyg/lexical/list/__tests__/unit/LexicalListNode.test.ts
@@ -6,7 +6,7 @@
  *
  */
 import {ParagraphNode, TextNode} from 'lexical';
-import {initializeUnitTest} from 'lexical/__tests__/utils';
+import {createTestContext} from 'lexical/__tests__/utils';
 
 import {
   $createListItemNode,
@@ -16,6 +16,7 @@ import {
   ListItemNode,
   ListNode,
 } from '../..';
+import {$htmlToBlockNodes} from "../../../../utils/nodes";
 
 const editorConfig = Object.freeze({
   namespace: '',
@@ -46,123 +47,122 @@ const editorConfig = Object.freeze({
 });
 
 describe('LexicalListNode tests', () => {
-  initializeUnitTest((testEnv) => {
-    test('ListNode.constructor', async () => {
-      const {editor} = testEnv;
+  test('ListNode.constructor', async () => {
+    const {editor} = createTestContext();
 
-      await editor.update(() => {
-        const listNode = $createListNode('bullet', 1);
-        expect(listNode.getType()).toBe('list');
-        expect(listNode.getTag()).toBe('ul');
-        expect(listNode.getTextContent()).toBe('');
-      });
-
-      // @ts-expect-error
-      expect(() => $createListNode()).toThrow();
+    await editor.update(() => {
+      const listNode = $createListNode('bullet', 1);
+      expect(listNode.getType()).toBe('list');
+      expect(listNode.getTag()).toBe('ul');
+      expect(listNode.getTextContent()).toBe('');
     });
 
-    test('ListNode.getTag()', async () => {
-      const {editor} = testEnv;
+    // @ts-expect-error
+    expect(() => $createListNode()).toThrow();
+  });
 
-      await editor.update(() => {
-        const ulListNode = $createListNode('bullet', 1);
-        expect(ulListNode.getTag()).toBe('ul');
-        const olListNode = $createListNode('number', 1);
-        expect(olListNode.getTag()).toBe('ol');
-        const checkListNode = $createListNode('check', 1);
-        expect(checkListNode.getTag()).toBe('ul');
-      });
+  test('ListNode.getTag()', async () => {
+    const {editor} = createTestContext();
+
+    await editor.update(() => {
+      const ulListNode = $createListNode('bullet', 1);
+      expect(ulListNode.getTag()).toBe('ul');
+      const olListNode = $createListNode('number', 1);
+      expect(olListNode.getTag()).toBe('ol');
+      const checkListNode = $createListNode('check', 1);
+      expect(checkListNode.getTag()).toBe('ul');
     });
+  });
 
-    test('ListNode.createDOM()', async () => {
-      const {editor} = testEnv;
+  test('ListNode.createDOM()', async () => {
+    const {editor} = createTestContext();
 
-      await editor.update(() => {
-        const listNode = $createListNode('bullet', 1);
-        expect(listNode.createDOM(editorConfig).outerHTML).toBe(
+    await editor.update(() => {
+      const listNode = $createListNode('bullet', 1);
+      expect(listNode.createDOM(editorConfig).outerHTML).toBe(
           '<ul class="my-ul-list-class my-ul-list-class-1"></ul>',
-        );
-        expect(
+      );
+      expect(
           listNode.createDOM({
             namespace: '',
             theme: {
               list: {},
             },
           }).outerHTML,
-        ).toBe('<ul></ul>');
-        expect(
+      ).toBe('<ul></ul>');
+      expect(
           listNode.createDOM({
             namespace: '',
             theme: {},
           }).outerHTML,
-        ).toBe('<ul></ul>');
-      });
+      ).toBe('<ul></ul>');
     });
+  });
 
-    test('ListNode.createDOM() correctly applies classes to a nested ListNode', async () => {
-      const {editor} = testEnv;
+  test('ListNode.createDOM() correctly applies classes to a nested ListNode', async () => {
+    const {editor} = createTestContext();
 
-      await editor.update(() => {
-        const listNode1 = $createListNode('bullet');
-        const listNode2 = $createListNode('bullet');
-        const listNode3 = $createListNode('bullet');
-        const listNode4 = $createListNode('bullet');
-        const listNode5 = $createListNode('bullet');
-        const listNode6 = $createListNode('bullet');
-        const listNode7 = $createListNode('bullet');
+    await editor.update(() => {
+      const listNode1 = $createListNode('bullet');
+      const listNode2 = $createListNode('bullet');
+      const listNode3 = $createListNode('bullet');
+      const listNode4 = $createListNode('bullet');
+      const listNode5 = $createListNode('bullet');
+      const listNode6 = $createListNode('bullet');
+      const listNode7 = $createListNode('bullet');
 
-        const listItem1 = $createListItemNode();
-        const listItem2 = $createListItemNode();
-        const listItem3 = $createListItemNode();
-        const listItem4 = $createListItemNode();
+      const listItem1 = $createListItemNode();
+      const listItem2 = $createListItemNode();
+      const listItem3 = $createListItemNode();
+      const listItem4 = $createListItemNode();
 
-        listNode1.append(listItem1);
-        listItem1.append(listNode2);
-        listNode2.append(listItem2);
-        listItem2.append(listNode3);
-        listNode3.append(listItem3);
-        listItem3.append(listNode4);
-        listNode4.append(listItem4);
-        listNode4.append(listNode5);
-        listNode5.append(listNode6);
-        listNode6.append(listNode7);
+      listNode1.append(listItem1);
+      listItem1.append(listNode2);
+      listNode2.append(listItem2);
+      listItem2.append(listNode3);
+      listNode3.append(listItem3);
+      listItem3.append(listNode4);
+      listNode4.append(listItem4);
+      listNode4.append(listNode5);
+      listNode5.append(listNode6);
+      listNode6.append(listNode7);
 
-        expect(listNode1.createDOM(editorConfig).outerHTML).toBe(
+      expect(listNode1.createDOM(editorConfig).outerHTML).toBe(
           '<ul class="my-ul-list-class my-ul-list-class-1"></ul>',
-        );
-        expect(
+      );
+      expect(
           listNode1.createDOM({
             namespace: '',
             theme: {
               list: {},
             },
           }).outerHTML,
-        ).toBe('<ul></ul>');
-        expect(
+      ).toBe('<ul></ul>');
+      expect(
           listNode1.createDOM({
             namespace: '',
             theme: {},
           }).outerHTML,
-        ).toBe('<ul></ul>');
-        expect(listNode2.createDOM(editorConfig).outerHTML).toBe(
+      ).toBe('<ul></ul>');
+      expect(listNode2.createDOM(editorConfig).outerHTML).toBe(
           '<ul class="my-ul-list-class my-ul-list-class-2"></ul>',
-        );
-        expect(listNode3.createDOM(editorConfig).outerHTML).toBe(
+      );
+      expect(listNode3.createDOM(editorConfig).outerHTML).toBe(
           '<ul class="my-ul-list-class my-ul-list-class-3"></ul>',
-        );
-        expect(listNode4.createDOM(editorConfig).outerHTML).toBe(
+      );
+      expect(listNode4.createDOM(editorConfig).outerHTML).toBe(
           '<ul class="my-ul-list-class my-ul-list-class-4"></ul>',
-        );
-        expect(listNode5.createDOM(editorConfig).outerHTML).toBe(
+      );
+      expect(listNode5.createDOM(editorConfig).outerHTML).toBe(
           '<ul class="my-ul-list-class my-ul-list-class-5"></ul>',
-        );
-        expect(listNode6.createDOM(editorConfig).outerHTML).toBe(
+      );
+      expect(listNode6.createDOM(editorConfig).outerHTML).toBe(
           '<ul class="my-ul-list-class my-ul-list-class-6"></ul>',
-        );
-        expect(listNode7.createDOM(editorConfig).outerHTML).toBe(
+      );
+      expect(listNode7.createDOM(editorConfig).outerHTML).toBe(
           '<ul class="my-ul-list-class my-ul-list-class-7"></ul>',
-        );
-        expect(
+      );
+      expect(
           listNode5.createDOM({
             namespace: '',
             theme: {
@@ -176,123 +176,135 @@ describe('LexicalListNode tests', () => {
               },
             },
           }).outerHTML,
-        ).toBe('<ul class="my-ul-list-class my-ul-list-class-2"></ul>');
-      });
+      ).toBe('<ul class="my-ul-list-class my-ul-list-class-2"></ul>');
     });
+  });
 
-    test('ListNode.updateDOM()', async () => {
-      const {editor} = testEnv;
+  test('ListNode.updateDOM()', async () => {
+    const {editor} = createTestContext();
 
-      await editor.update(() => {
-        const listNode = $createListNode('bullet', 1);
-        const domElement = listNode.createDOM(editorConfig);
+    await editor.update(() => {
+      const listNode = $createListNode('bullet', 1);
+      const domElement = listNode.createDOM(editorConfig);
 
-        expect(domElement.outerHTML).toBe(
+      expect(domElement.outerHTML).toBe(
           '<ul class="my-ul-list-class my-ul-list-class-1"></ul>',
-        );
+      );
 
-        const newListNode = $createListNode('number', 1);
-        const result = newListNode.updateDOM(
+      const newListNode = $createListNode('number', 1);
+      const result = newListNode.updateDOM(
           listNode,
           domElement,
           editorConfig,
-        );
+      );
 
-        expect(result).toBe(true);
-        expect(domElement.outerHTML).toBe(
+      expect(result).toBe(true);
+      expect(domElement.outerHTML).toBe(
           '<ul class="my-ul-list-class my-ul-list-class-1"></ul>',
-        );
-      });
-    });
-
-    test('ListNode.append() should properly transform a ListItemNode', async () => {
-      const {editor} = testEnv;
-
-      await editor.update(() => {
-        const listNode = new ListNode('bullet', 1);
-        const listItemNode = new ListItemNode();
-        const textNode = new TextNode('Hello');
-
-        listItemNode.append(textNode);
-        const nodesToAppend = [listItemNode];
-
-        expect(listNode.append(...nodesToAppend)).toBe(listNode);
-        expect(listNode.getFirstChild()).toBe(listItemNode);
-        expect(listNode.getFirstChild()?.getTextContent()).toBe('Hello');
-      });
-    });
-
-    test('ListNode.append() should properly transform a ListNode', async () => {
-      const {editor} = testEnv;
-
-      await editor.update(() => {
-        const listNode = new ListNode('bullet', 1);
-        const nestedListNode = new ListNode('bullet', 1);
-        const listItemNode = new ListItemNode();
-        const textNode = new TextNode('Hello');
-
-        listItemNode.append(textNode);
-        nestedListNode.append(listItemNode);
-
-        const nodesToAppend = [nestedListNode];
-
-        expect(listNode.append(...nodesToAppend)).toBe(listNode);
-        expect($isListItemNode(listNode.getFirstChild())).toBe(true);
-        expect(listNode.getFirstChild<ListItemNode>()!.getFirstChild()).toBe(
-          nestedListNode,
-        );
-      });
-    });
-
-    test('ListNode.append() should properly transform a ParagraphNode', async () => {
-      const {editor} = testEnv;
-
-      await editor.update(() => {
-        const listNode = new ListNode('bullet', 1);
-        const paragraph = new ParagraphNode();
-        const textNode = new TextNode('Hello');
-        paragraph.append(textNode);
-        const nodesToAppend = [paragraph];
-
-        expect(listNode.append(...nodesToAppend)).toBe(listNode);
-        expect($isListItemNode(listNode.getFirstChild())).toBe(true);
-        expect(listNode.getFirstChild()?.getTextContent()).toBe('Hello');
-      });
-    });
-
-    test('$createListNode()', async () => {
-      const {editor} = testEnv;
-
-      await editor.update(() => {
-        const listNode = $createListNode('bullet', 1);
-        const createdListNode = $createListNode('bullet');
-
-        expect(listNode.__type).toEqual(createdListNode.__type);
-        expect(listNode.__parent).toEqual(createdListNode.__parent);
-        expect(listNode.__tag).toEqual(createdListNode.__tag);
-        expect(listNode.__key).not.toEqual(createdListNode.__key);
-      });
-    });
-
-    test('$isListNode()', async () => {
-      const {editor} = testEnv;
-
-      await editor.update(() => {
-        const listNode = $createListNode('bullet', 1);
-
-        expect($isListNode(listNode)).toBe(true);
-      });
-    });
-
-    test('$createListNode() with tag name (backward compatibility)', async () => {
-      const {editor} = testEnv;
-
-      await editor.update(() => {
-        const numberList = $createListNode('number', 1);
-        const bulletList = $createListNode('bullet', 1);
-        expect(numberList.__listType).toBe('number');
-        expect(bulletList.__listType).toBe('bullet');
-      });
+      );
     });
   });
+
+  test('ListNode.append() should properly transform a ListItemNode', async () => {
+    const {editor} = createTestContext();
+
+    await editor.update(() => {
+      const listNode = new ListNode('bullet', 1);
+      const listItemNode = new ListItemNode();
+      const textNode = new TextNode('Hello');
+
+      listItemNode.append(textNode);
+      const nodesToAppend = [listItemNode];
+
+      expect(listNode.append(...nodesToAppend)).toBe(listNode);
+      expect(listNode.getFirstChild()).toBe(listItemNode);
+      expect(listNode.getFirstChild()?.getTextContent()).toBe('Hello');
+    });
+  });
+
+  test('ListNode.append() should properly transform a ListNode', async () => {
+    const {editor} = createTestContext();
+
+    await editor.update(() => {
+      const listNode = new ListNode('bullet', 1);
+      const nestedListNode = new ListNode('bullet', 1);
+      const listItemNode = new ListItemNode();
+      const textNode = new TextNode('Hello');
+
+      listItemNode.append(textNode);
+      nestedListNode.append(listItemNode);
+
+      const nodesToAppend = [nestedListNode];
+
+      expect(listNode.append(...nodesToAppend)).toBe(listNode);
+      expect($isListItemNode(listNode.getFirstChild())).toBe(true);
+      expect(listNode.getFirstChild<ListItemNode>()!.getFirstChild()).toBe(
+          nestedListNode,
+      );
+    });
+  });
+
+  test('ListNode.append() should properly transform a ParagraphNode', async () => {
+    const {editor} = createTestContext();
+
+    await editor.update(() => {
+      const listNode = new ListNode('bullet', 1);
+      const paragraph = new ParagraphNode();
+      const textNode = new TextNode('Hello');
+      paragraph.append(textNode);
+      const nodesToAppend = [paragraph];
+
+      expect(listNode.append(...nodesToAppend)).toBe(listNode);
+      expect($isListItemNode(listNode.getFirstChild())).toBe(true);
+      expect(listNode.getFirstChild()?.getTextContent()).toBe('Hello');
+    });
+  });
+
+  test('$createListNode()', async () => {
+    const {editor} = createTestContext();
+
+    await editor.update(() => {
+      const listNode = $createListNode('bullet', 1);
+      const createdListNode = $createListNode('bullet');
+
+      expect(listNode.__type).toEqual(createdListNode.__type);
+      expect(listNode.__parent).toEqual(createdListNode.__parent);
+      expect(listNode.__tag).toEqual(createdListNode.__tag);
+      expect(listNode.__key).not.toEqual(createdListNode.__key);
+    });
+  });
+
+  test('$isListNode()', async () => {
+    const {editor} = createTestContext();
+
+    await editor.update(() => {
+      const listNode = $createListNode('bullet', 1);
+
+      expect($isListNode(listNode)).toBe(true);
+    });
+  });
+
+  test('$createListNode() with tag name (backward compatibility)', async () => {
+    const {editor} = createTestContext();
+
+    await editor.update(() => {
+      const numberList = $createListNode('number', 1);
+      const bulletList = $createListNode('bullet', 1);
+      expect(numberList.__listType).toBe('number');
+      expect(bulletList.__listType).toBe('bullet');
+    });
+  });
+
+  test('importDOM handles old editor expected task list format', async () => {
+    const {editor} = createTestContext();
+
+    let list!: ListNode;
+    editor.update(() => {
+      const nodes = $htmlToBlockNodes(editor, `<ul><li class="task-list-item"><input checked="" disabled="" type="checkbox"> A</li></ul>`);
+      list = nodes[0] as ListNode;
+    });
+
+    expect(list).toBeInstanceOf(ListNode);
+    expect(list.getListType()).toBe('check');
+  });
 });
diff --git a/resources/js/wysiwyg/lexical/rich-text/LexicalImageNode.ts b/resources/js/wysiwyg/lexical/rich-text/LexicalImageNode.ts
index 9f42ad732..40f4ab711 100644
--- a/resources/js/wysiwyg/lexical/rich-text/LexicalImageNode.ts
+++ b/resources/js/wysiwyg/lexical/rich-text/LexicalImageNode.ts
@@ -133,7 +133,7 @@ export class ImageNode extends ElementNode {
 
         element.addEventListener('click', e => {
             _editor.update(() => {
-                $selectSingleNode(this);
+                this.select();
             });
         });
 
diff --git a/resources/js/wysiwyg/services/__tests__/keyboard-handling.test.ts b/resources/js/wysiwyg/services/__tests__/keyboard-handling.test.ts
index 736c3573c..cd4235f2f 100644
--- a/resources/js/wysiwyg/services/__tests__/keyboard-handling.test.ts
+++ b/resources/js/wysiwyg/services/__tests__/keyboard-handling.test.ts
@@ -1,7 +1,7 @@
 import {
     createTestContext, destroyFromContext,
     dispatchKeydownEventForNode,
-    dispatchKeydownEventForSelectedNode,
+    dispatchKeydownEventForSelectedNode, expectNodeShapeToMatch,
 } from "lexical/__tests__/utils";
 import {
     $createParagraphNode, $createTextNode,
@@ -13,6 +13,7 @@ import {registerKeyboardHandling} from "../keyboard-handling";
 import {registerRichText} from "@lexical/rich-text";
 import {EditorUiContext} from "../../ui/framework/core";
 import {$createListItemNode, $createListNode, ListItemNode, ListNode} from "@lexical/list";
+import {$createImageNode, ImageNode} from "@lexical/rich-text/LexicalImageNode";
 
 describe('Keyboard-handling service tests', () => {
 
@@ -127,4 +128,34 @@ describe('Keyboard-handling service tests', () => {
             expect(selectedNode?.getKey()).toBe(innerList.getChildren()[0].getKey());
         });
     });
+
+    test('Images: up on selected image creates new paragraph if none above', () => {
+        let image!: ImageNode;
+        editor.updateAndCommit(() => {
+            const root = $getRoot();
+            const imageWrap = $createParagraphNode();
+            image = $createImageNode('https://example.com/cat.png');
+            imageWrap.append(image);
+            root.append(imageWrap);
+            image.select();
+        });
+
+        expectNodeShapeToMatch(editor, [{
+            type: 'paragraph',
+            children: [
+                {type: 'image'}
+            ],
+        }]);
+
+        dispatchKeydownEventForNode(image, editor, 'ArrowUp');
+
+        expectNodeShapeToMatch(editor, [{
+            type: 'paragraph',
+        }, {
+            type: 'paragraph',
+            children: [
+                {type: 'image'}
+            ],
+        }]);
+    });
 });
\ No newline at end of file
diff --git a/resources/js/wysiwyg/services/keyboard-handling.ts b/resources/js/wysiwyg/services/keyboard-handling.ts
index ff6117b2b..a7f1ec7f0 100644
--- a/resources/js/wysiwyg/services/keyboard-handling.ts
+++ b/resources/js/wysiwyg/services/keyboard-handling.ts
@@ -3,7 +3,7 @@ import {
     $createParagraphNode,
     $getSelection,
     $isDecoratorNode,
-    COMMAND_PRIORITY_LOW, KEY_ARROW_DOWN_COMMAND,
+    COMMAND_PRIORITY_LOW, KEY_ARROW_DOWN_COMMAND, KEY_ARROW_UP_COMMAND,
     KEY_BACKSPACE_COMMAND,
     KEY_DELETE_COMMAND,
     KEY_ENTER_COMMAND, KEY_TAB_COMMAND,
@@ -43,7 +43,7 @@ function deleteSingleSelectedNode(editor: LexicalEditor) {
 }
 
 /**
- * Insert a new empty node after the selection if the selection contains a single
+ * Insert a new empty node before/after the selection if the selection contains a single
  * selected node (like image, media etc...).
  */
 function insertAfterSingleSelectedNode(editor: LexicalEditor, event: KeyboardEvent|null): boolean {
@@ -67,6 +67,34 @@ function insertAfterSingleSelectedNode(editor: LexicalEditor, event: KeyboardEve
     return false;
 }
 
+function focusAdjacentOrInsertForSingleSelectNode(editor: LexicalEditor, event: KeyboardEvent|null, after: boolean = true): boolean {
+    const selectionNodes = getLastSelection(editor)?.getNodes() || [];
+    if (!isSingleSelectedNode(selectionNodes)) {
+        return false;
+    }
+
+    event?.preventDefault();
+
+    const node = selectionNodes[0];
+    const nearestBlock = $getNearestNodeBlockParent(node) || node;
+    let target = after ? nearestBlock.getNextSibling() : nearestBlock.getPreviousSibling();
+
+    editor.update(() => {
+        if (!target) {
+            target = $createParagraphNode();
+            if (after) {
+                nearestBlock.insertAfter(target)
+            } else {
+                nearestBlock.insertBefore(target);
+            }
+        }
+
+        target.selectStart();
+    });
+
+    return true;
+}
+
 /**
  * Insert a new node after a details node, if inside a details node that's
  * the last element, and if the cursor is at the last block within the details node.
@@ -199,8 +227,13 @@ export function registerKeyboardHandling(context: EditorUiContext): () => void {
         return handleInsetOnTab(context.editor, event);
     }, COMMAND_PRIORITY_LOW);
 
+    const unregisterUp = context.editor.registerCommand(KEY_ARROW_UP_COMMAND, (event): boolean => {
+        return focusAdjacentOrInsertForSingleSelectNode(context.editor, event, false);
+    }, COMMAND_PRIORITY_LOW);
+
     const unregisterDown = context.editor.registerCommand(KEY_ARROW_DOWN_COMMAND, (event): boolean => {
-        return insertAfterDetails(context.editor, event);
+        return insertAfterDetails(context.editor, event)
+            || focusAdjacentOrInsertForSingleSelectNode(context.editor, event, true)
     }, COMMAND_PRIORITY_LOW);
 
     return () => {
@@ -208,6 +241,7 @@ export function registerKeyboardHandling(context: EditorUiContext): () => void {
         unregisterDelete();
         unregisterEnter();
         unregisterTab();
+        unregisterUp();
         unregisterDown();
     };
 }
\ No newline at end of file
diff --git a/resources/js/wysiwyg/utils/lists.ts b/resources/js/wysiwyg/utils/lists.ts
index 005b05f98..3deb9dfb6 100644
--- a/resources/js/wysiwyg/utils/lists.ts
+++ b/resources/js/wysiwyg/utils/lists.ts
@@ -1,6 +1,6 @@
 import {$createTextNode, $getSelection, BaseSelection, LexicalEditor, TextNode} from "lexical";
 import {$getBlockElementNodesInSelection, $selectNodes, $toggleSelection} from "./selection";
-import {nodeHasInset} from "./nodes";
+import {$sortNodes, nodeHasInset} from "./nodes";
 import {$createListItemNode, $createListNode, $isListItemNode, $isListNode, ListItemNode} from "@lexical/list";
 
 
@@ -49,16 +49,11 @@ export function $unnestListItem(node: ListItemNode): ListItemNode {
     }
 
     const laterSiblings = node.getNextSiblings();
-
     parentListItem.insertAfter(node);
     if (list.getChildren().length === 0) {
         list.remove();
     }
 
-    if (parentListItem.getChildren().length === 0) {
-        parentListItem.remove();
-    }
-
     if (laterSiblings.length > 0) {
         const childList = $createListNode(list.getListType());
         childList.append(...laterSiblings);
@@ -69,23 +64,54 @@ export function $unnestListItem(node: ListItemNode): ListItemNode {
         list.remove();
     }
 
+    if (parentListItem.getChildren().length === 0) {
+        parentListItem.remove();
+    }
+
     return node;
 }
 
 function getListItemsForSelection(selection: BaseSelection|null): (ListItemNode|null)[] {
     const nodes = selection?.getNodes() || [];
-    const listItemNodes = [];
+    let [start, end] = selection?.getStartEndPoints() || [null, null];
 
+    // Ensure we ignore parent list items of the top-most list item since,
+    // although technically part of the selection, from a user point of
+    // view the selection does not spread to encompass this outer element.
+    const itemsToIgnore: Set<string> = new Set();
+    if (selection && start) {
+        if (selection.isBackward() && end) {
+            [end, start] = [start, end];
+        }
+
+        const startParents = start.getNode().getParents();
+        let foundList = false;
+        for (const parent of startParents) {
+            if ($isListItemNode(parent)) {
+                if (foundList) {
+                    itemsToIgnore.add(parent.getKey());
+                } else {
+                    foundList = true;
+                }
+            }
+        }
+    }
+
+    const listItemNodes = [];
     outer: for (const node of nodes) {
         if ($isListItemNode(node)) {
-            listItemNodes.push(node);
+            if (!itemsToIgnore.has(node.getKey())) {
+                listItemNodes.push(node);
+            }
             continue;
         }
 
         const parents = node.getParents();
         for (const parent of parents) {
             if ($isListItemNode(parent)) {
-                listItemNodes.push(parent);
+                if (!itemsToIgnore.has(parent.getKey())) {
+                    listItemNodes.push(parent);
+                }
                 continue outer;
             }
         }
@@ -110,7 +136,8 @@ function $reduceDedupeListItems(listItems: (ListItemNode|null)[]): ListItemNode[
         }
     }
 
-    return Object.values(listItemMap);
+    const items = Object.values(listItemMap);
+    return $sortNodes(items) as ListItemNode[];
 }
 
 export function $setInsetForSelection(editor: LexicalEditor, change: number): void {
diff --git a/resources/js/wysiwyg/utils/nodes.ts b/resources/js/wysiwyg/utils/nodes.ts
index b5cc78955..591232ea3 100644
--- a/resources/js/wysiwyg/utils/nodes.ts
+++ b/resources/js/wysiwyg/utils/nodes.ts
@@ -94,6 +94,30 @@ export function $getNearestNodeBlockParent(node: LexicalNode): LexicalNode|null
     return $findMatchingParent(node, isBlockNode);
 }
 
+export function $sortNodes(nodes: LexicalNode[]): LexicalNode[] {
+    const idChain: string[] = [];
+    const addIds = (n: ElementNode) => {
+        for (const child of n.getChildren()) {
+            idChain.push(child.getKey())
+            if ($isElementNode(child)) {
+                addIds(child)
+            }
+        }
+    };
+
+    const root = $getRoot();
+    addIds(root);
+
+    const sorted = Array.from(nodes);
+    sorted.sort((a, b) => {
+        const aIndex = idChain.indexOf(a.getKey());
+        const bIndex = idChain.indexOf(b.getKey());
+        return aIndex - bIndex;
+    });
+
+    return sorted;
+}
+
 export function nodeHasAlignment(node: object): node is NodeHasAlignment {
     return '__alignment' in node;
 }
diff --git a/resources/sass/_editor.scss b/resources/sass/_editor.scss
index 9f7694e85..35f11c5a2 100644
--- a/resources/sass/_editor.scss
+++ b/resources/sass/_editor.scss
@@ -370,8 +370,10 @@ body.editor-is-fullscreen {
   display: inline-block;
   outline: 2px dashed var(--editor-color-primary);
   direction: ltr;
+  pointer-events: none;
 }
 .editor-node-resizer-handle {
+  pointer-events: auto;
   position: absolute;
   display: block;
   width: 10px;