33 $createParagraphNode ,
44 $getSelection ,
55 $isDecoratorNode ,
6- COMMAND_PRIORITY_LOW , KEY_ARROW_DOWN_COMMAND ,
6+ COMMAND_PRIORITY_LOW , KEY_ARROW_DOWN_COMMAND , KEY_ARROW_UP_COMMAND ,
77 KEY_BACKSPACE_COMMAND ,
88 KEY_DELETE_COMMAND ,
99 KEY_ENTER_COMMAND , KEY_TAB_COMMAND ,
@@ -43,7 +43,7 @@ function deleteSingleSelectedNode(editor: LexicalEditor) {
4343}
4444
4545/**
46- * Insert a new empty node after the selection if the selection contains a single
46+ * Insert a new empty node before/ after the selection if the selection contains a single
4747 * selected node (like image, media etc...).
4848 */
4949function insertAfterSingleSelectedNode ( editor : LexicalEditor , event : KeyboardEvent | null ) : boolean {
@@ -67,6 +67,37 @@ function insertAfterSingleSelectedNode(editor: LexicalEditor, event: KeyboardEve
6767 return false ;
6868}
6969
70+ function focusAdjacentOrInsertForSingleSelectNode ( editor : LexicalEditor , event : KeyboardEvent | null , after : boolean = true ) : boolean {
71+ const selectionNodes = getLastSelection ( editor ) ?. getNodes ( ) || [ ] ;
72+ if ( ! isSingleSelectedNode ( selectionNodes ) ) {
73+ return false ;
74+ }
75+
76+ event ?. preventDefault ( ) ;
77+
78+ const node = selectionNodes [ 0 ] ;
79+ const nearestBlock = $getNearestNodeBlockParent ( node ) || node ;
80+ let target = after ? nearestBlock . getNextSibling ( ) : nearestBlock . getPreviousSibling ( ) ;
81+
82+ requestAnimationFrame ( ( ) => {
83+ editor . update ( ( ) => {
84+ if ( ! target ) {
85+ target = $createParagraphNode ( ) ;
86+ if ( after ) {
87+ nearestBlock . insertAfter ( target )
88+ } else {
89+ nearestBlock . insertBefore ( target ) ;
90+ }
91+ }
92+
93+ target . selectStart ( ) ;
94+ } ) ;
95+ } ) ;
96+
97+
98+ return true ;
99+ }
100+
70101/**
71102 * Insert a new node after a details node, if inside a details node that's
72103 * the last element, and if the cursor is at the last block within the details node.
@@ -199,15 +230,21 @@ export function registerKeyboardHandling(context: EditorUiContext): () => void {
199230 return handleInsetOnTab ( context . editor , event ) ;
200231 } , COMMAND_PRIORITY_LOW ) ;
201232
233+ const unregisterUp = context . editor . registerCommand ( KEY_ARROW_UP_COMMAND , ( event ) : boolean => {
234+ return focusAdjacentOrInsertForSingleSelectNode ( context . editor , event , false ) ;
235+ } , COMMAND_PRIORITY_LOW ) ;
236+
202237 const unregisterDown = context . editor . registerCommand ( KEY_ARROW_DOWN_COMMAND , ( event ) : boolean => {
203- return insertAfterDetails ( context . editor , event ) ;
238+ return insertAfterDetails ( context . editor , event )
239+ || focusAdjacentOrInsertForSingleSelectNode ( context . editor , event , true )
204240 } , COMMAND_PRIORITY_LOW ) ;
205241
206242 return ( ) => {
207243 unregisterBackspace ( ) ;
208244 unregisterDelete ( ) ;
209245 unregisterEnter ( ) ;
210246 unregisterTab ( ) ;
247+ unregisterUp ( ) ;
211248 unregisterDown ( ) ;
212249 } ;
213250}
0 commit comments