Skip to content

Commit 9bfcadd

Browse files
committed
Lexical: Improved navigation around images/media
- Added specific handling to move/insert-up/down on arrow press. - Prevented resize overlay from interrupting image node focus.
1 parent 62c8eb3 commit 9bfcadd

File tree

3 files changed

+43
-4
lines changed

3 files changed

+43
-4
lines changed

resources/js/wysiwyg/lexical/rich-text/LexicalImageNode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ export class ImageNode extends ElementNode {
133133

134134
element.addEventListener('click', e => {
135135
_editor.update(() => {
136-
$selectSingleNode(this);
136+
this.select();
137137
});
138138
});
139139

resources/js/wysiwyg/services/keyboard-handling.ts

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import {
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
*/
4949
function 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
}

resources/sass/_editor.scss

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,8 +370,10 @@ body.editor-is-fullscreen {
370370
display: inline-block;
371371
outline: 2px dashed var(--editor-color-primary);
372372
direction: ltr;
373+
pointer-events: none;
373374
}
374375
.editor-node-resizer-handle {
376+
pointer-events: auto;
375377
position: absolute;
376378
display: block;
377379
width: 10px;

0 commit comments

Comments
 (0)