-
Notifications
You must be signed in to change notification settings - Fork 1.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add shift+up and shift+down support for decorator nodes #4586
Changes from all commits
31c68d7
2f10f89
5c3ded1
cccf001
503923a
eb64a99
45c5ea4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -711,6 +711,72 @@ export function registerRichText(editor: LexicalEditor): () => void { | |
KEY_ARROW_UP_COMMAND, | ||
(event) => { | ||
const selection = $getSelection(); | ||
if (event.shiftKey) { | ||
if ($isRangeSelection(selection)) { | ||
const anchorNode = selection.anchor.getNode(); | ||
|
||
if (!$isRootNode(anchorNode)) { | ||
const anchorNodeTopElement = anchorNode.getTopLevelElement(); | ||
const focusNode = selection.focus.getNode().getTopLevelElement(); | ||
|
||
if (!focusNode || !anchorNodeTopElement) { | ||
return false; | ||
} | ||
const focusNodeTopElement = focusNode.getTopLevelElement(); | ||
if (!focusNodeTopElement) { | ||
return false; | ||
} | ||
|
||
// if on or about to move to decorator node selection, select the entire current node using root node offsets | ||
const previousSibling = focusNodeTopElement.getPreviousSibling(); | ||
if ( | ||
$isDecoratorNode(anchorNodeTopElement) || | ||
$isDecoratorNode(previousSibling) | ||
) { | ||
// if at the start of the line, treat that line/node as not selected | ||
if (selection.anchor.offset === 0) { | ||
selection.focus.set( | ||
'root', | ||
focusNode.getIndexWithinParent() - 1, | ||
'element', | ||
); | ||
selection.anchor.set( | ||
'root', | ||
anchorNodeTopElement.getIndexWithinParent(), | ||
'element', | ||
); | ||
} else { | ||
selection.focus.set( | ||
'root', | ||
focusNode.getIndexWithinParent(), | ||
'element', | ||
); | ||
selection.anchor.set( | ||
'root', | ||
anchorNodeTopElement.getIndexWithinParent() + 1, | ||
'element', | ||
); | ||
Comment on lines
+754
to
+758
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we need to modify the anchor selection? I presume this one's correct already? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No - it would be correct, it just felt better to be consistent about shifting to using There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If removed, this would have an impact on the change made in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If removed, this would have an impact on the change made in |
||
} | ||
event.preventDefault(); | ||
return true; | ||
} | ||
} | ||
|
||
// if using the root node, simply add the card above | ||
9larsons marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if ($isRootNode(anchorNode)) { | ||
const offset = selection.focus.offset; | ||
if (offset > 0) { | ||
selection.focus.set( | ||
'root', | ||
selection.focus.offset - 1, | ||
'element', | ||
); | ||
} | ||
event.preventDefault(); | ||
return true; | ||
} | ||
} | ||
} | ||
if ( | ||
$isNodeSelection(selection) && | ||
!$isTargetWithinDecorator(event.target as HTMLElement) | ||
|
@@ -743,6 +809,80 @@ export function registerRichText(editor: LexicalEditor): () => void { | |
KEY_ARROW_DOWN_COMMAND, | ||
(event) => { | ||
const selection = $getSelection(); | ||
|
||
if (event.shiftKey) { | ||
9larsons marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if ($isRangeSelection(selection)) { | ||
const anchorNode = selection.anchor.getNode(); | ||
|
||
if (!$isRootNode(anchorNode)) { | ||
const anchorNodeTopElement = anchorNode.getTopLevelElement(); | ||
const focusNode = selection.focus.getNode().getTopLevelElement(); | ||
|
||
if (!focusNode || !anchorNodeTopElement) { | ||
return false; | ||
} | ||
const focusNodeTopElement = focusNode.getTopLevelElement(); | ||
if (!focusNodeTopElement) { | ||
return false; | ||
} | ||
|
||
// if on or about to move to decorator node selection, select the entire current node using root node offsets | ||
const nextSibling = focusNodeTopElement.getNextSibling(); | ||
if ( | ||
$isDecoratorNode(anchorNodeTopElement) || | ||
$isDecoratorNode(nextSibling) | ||
) { | ||
// if at end of a line, treat it as if that line/node is not selected | ||
if ( | ||
selection.anchor.offset === | ||
anchorNodeTopElement.getTextContentSize() | ||
) { | ||
selection.anchor.set( | ||
'root', | ||
anchorNodeTopElement.getIndexWithinParent() + 1, | ||
'element', | ||
); | ||
selection.focus.set( | ||
'root', | ||
focusNode.getIndexWithinParent() + 2, | ||
'element', | ||
); | ||
} else { | ||
selection.anchor.set( | ||
'root', | ||
anchorNodeTopElement.getIndexWithinParent(), | ||
'element', | ||
); | ||
selection.focus.set( | ||
'root', | ||
focusNode.getIndexWithinParent() + 1, | ||
'element', | ||
); | ||
} | ||
event.preventDefault(); | ||
return true; | ||
} | ||
} | ||
|
||
// if using the root node, simply add the node below | ||
if ($isRootNode(anchorNode)) { | ||
const offset = selection.focus.offset; | ||
if ( | ||
offset <= | ||
anchorNode.getLastChildOrThrow().getIndexWithinParent() | ||
) { | ||
selection.focus.set( | ||
'root', | ||
selection.focus.offset + 1, | ||
'element', | ||
); | ||
} | ||
event.preventDefault(); | ||
return true; | ||
} | ||
} | ||
} | ||
|
||
if ($isNodeSelection(selection)) { | ||
// If selection is on a node, let's try and move selection | ||
// back to being a range selection. | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can't assume that offset 0 is start of the line, for example
Screen.Recording.2023-06-01.at.6.44.55.am.mov
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not certain how you managed this - could you explain?