X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/ace8af077dfa5173c24cdf8b50eb82ccbd1dbf7e..refs/pull/5591/head:/resources/js/wysiwyg/services/keyboard-handling.ts 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