mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-08-09 00:36:41 +02:00
fix arrow key behavior on void nodes
This commit is contained in:
@@ -488,6 +488,31 @@ const Node = {
|
|||||||
.reduce((marks, char) => marks.union(char.marks), marks)
|
.reduce((marks, char) => marks.union(char.marks), marks)
|
||||||
},
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the block node before a descendant text node by `key`.
|
||||||
|
*
|
||||||
|
* @param {String or Node} key
|
||||||
|
* @return {Node or Null} node
|
||||||
|
*/
|
||||||
|
|
||||||
|
getNextBlock(key) {
|
||||||
|
key = normalizeKey(key)
|
||||||
|
const child = this.getDescendant(key)
|
||||||
|
let last
|
||||||
|
|
||||||
|
if (child.kind == 'block') {
|
||||||
|
last = child.getTextNodes().last()
|
||||||
|
} else {
|
||||||
|
const block = this.getClosestBlock(key)
|
||||||
|
last = block.getTextNodes().last()
|
||||||
|
}
|
||||||
|
|
||||||
|
const next = this.getNextText(last)
|
||||||
|
if (!next) return null
|
||||||
|
|
||||||
|
return this.getClosestBlock(next)
|
||||||
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the node after a descendant by `key`.
|
* Get the node after a descendant by `key`.
|
||||||
*
|
*
|
||||||
|
@@ -557,6 +557,161 @@ class State extends Record(DEFAULTS) {
|
|||||||
if (!previous) return state
|
if (!previous) return state
|
||||||
|
|
||||||
selection = selection.moveToStartOf(previous)
|
selection = selection.moveToStartOf(previous)
|
||||||
|
selection = selection.normalize(document)
|
||||||
|
state = state.merge({ selection })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the selection to the end of the previous block.
|
||||||
|
*
|
||||||
|
* @return {State} state
|
||||||
|
*/
|
||||||
|
|
||||||
|
moveToEndOfPreviousBlock() {
|
||||||
|
let state = this
|
||||||
|
let { document, selection } = state
|
||||||
|
let blocks = document.getBlocksAtRange(selection)
|
||||||
|
let block = blocks.first()
|
||||||
|
if (!block) return state
|
||||||
|
|
||||||
|
let previous = document.getPreviousBlock(block)
|
||||||
|
if (!previous) return state
|
||||||
|
|
||||||
|
selection = selection.moveToEndOf(previous)
|
||||||
|
selection = selection.normalize(document)
|
||||||
|
state = state.merge({ selection })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the selection to the start of the next block.
|
||||||
|
*
|
||||||
|
* @return {State} state
|
||||||
|
*/
|
||||||
|
|
||||||
|
moveToStartOfNextBlock() {
|
||||||
|
let state = this
|
||||||
|
let { document, selection } = state
|
||||||
|
let blocks = document.getBlocksAtRange(selection)
|
||||||
|
let block = blocks.last()
|
||||||
|
if (!block) return state
|
||||||
|
|
||||||
|
let next = document.getNextBlock(block)
|
||||||
|
if (!next) return state
|
||||||
|
|
||||||
|
selection = selection.moveToStartOf(next)
|
||||||
|
selection = selection.normalize(document)
|
||||||
|
state = state.merge({ selection })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the selection to the end of the next block.
|
||||||
|
*
|
||||||
|
* @return {State} state
|
||||||
|
*/
|
||||||
|
|
||||||
|
moveToEndOfNextBlock() {
|
||||||
|
let state = this
|
||||||
|
let { document, selection } = state
|
||||||
|
let blocks = document.getBlocksAtRange(selection)
|
||||||
|
let block = blocks.last()
|
||||||
|
if (!block) return state
|
||||||
|
|
||||||
|
let next = document.getNextBlock(block)
|
||||||
|
if (!next) return state
|
||||||
|
|
||||||
|
selection = selection.moveToEndOf(next)
|
||||||
|
selection = selection.normalize(document)
|
||||||
|
state = state.merge({ selection })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the selection to the start of the previous text.
|
||||||
|
*
|
||||||
|
* @return {State} state
|
||||||
|
*/
|
||||||
|
|
||||||
|
moveToStartOfPreviousText() {
|
||||||
|
let state = this
|
||||||
|
let { document, selection } = state
|
||||||
|
let texts = document.getTextsAtRange(selection)
|
||||||
|
let text = texts.first()
|
||||||
|
if (!text) return state
|
||||||
|
|
||||||
|
let previous = document.getPreviousText(text)
|
||||||
|
if (!previous) return state
|
||||||
|
|
||||||
|
selection = selection.moveToStartOf(previous)
|
||||||
|
selection = selection.normalize(document)
|
||||||
|
state = state.merge({ selection })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the selection to the end of the previous text.
|
||||||
|
*
|
||||||
|
* @return {State} state
|
||||||
|
*/
|
||||||
|
|
||||||
|
moveToEndOfPreviousText() {
|
||||||
|
let state = this
|
||||||
|
let { document, selection } = state
|
||||||
|
let texts = document.getTextsAtRange(selection)
|
||||||
|
let text = texts.first()
|
||||||
|
if (!text) return state
|
||||||
|
|
||||||
|
let previous = document.getPreviousText(text)
|
||||||
|
if (!previous) return state
|
||||||
|
|
||||||
|
selection = selection.moveToEndOf(previous)
|
||||||
|
selection = selection.normalize(document)
|
||||||
|
state = state.merge({ selection })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the selection to the start of the next text.
|
||||||
|
*
|
||||||
|
* @return {State} state
|
||||||
|
*/
|
||||||
|
|
||||||
|
moveToStartOfNextText() {
|
||||||
|
let state = this
|
||||||
|
let { document, selection } = state
|
||||||
|
let texts = document.getTextsAtRange(selection)
|
||||||
|
let text = texts.last()
|
||||||
|
if (!text) return state
|
||||||
|
|
||||||
|
let next = document.getNextText(text)
|
||||||
|
if (!next) return state
|
||||||
|
|
||||||
|
selection = selection.moveToStartOf(next)
|
||||||
|
selection = selection.normalize(document)
|
||||||
|
state = state.merge({ selection })
|
||||||
|
return state
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Move the selection to the end of the next text.
|
||||||
|
*
|
||||||
|
* @return {State} state
|
||||||
|
*/
|
||||||
|
|
||||||
|
moveToEndOfNextText() {
|
||||||
|
let state = this
|
||||||
|
let { document, selection } = state
|
||||||
|
let texts = document.getTextsAtRange(selection)
|
||||||
|
let text = texts.last()
|
||||||
|
if (!text) return state
|
||||||
|
|
||||||
|
let next = document.getNextText(text)
|
||||||
|
if (!next) return state
|
||||||
|
|
||||||
|
selection = selection.moveToEndOf(next)
|
||||||
|
selection = selection.normalize(document)
|
||||||
state = state.merge({ selection })
|
state = state.merge({ selection })
|
||||||
return state
|
return state
|
||||||
}
|
}
|
||||||
|
@@ -76,6 +76,13 @@ const STATE_TRANSFORMS = [
|
|||||||
'insertText',
|
'insertText',
|
||||||
'mark',
|
'mark',
|
||||||
'moveToStartOfPreviousBlock',
|
'moveToStartOfPreviousBlock',
|
||||||
|
'moveToEndOfPreviousBlock',
|
||||||
|
'moveToStartOfNextBlock',
|
||||||
|
'moveToEndOfNextBlock',
|
||||||
|
'moveToStartOfPreviousText',
|
||||||
|
'moveToEndOfPreviousText',
|
||||||
|
'moveToStartOfNextText',
|
||||||
|
'moveToEndOfNextText',
|
||||||
'setBlock',
|
'setBlock',
|
||||||
'setInline',
|
'setInline',
|
||||||
'splitBlock',
|
'splitBlock',
|
||||||
|
@@ -63,6 +63,38 @@ export default {
|
|||||||
: transform.deleteForward().apply()
|
: transform.deleteForward().apply()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case 'up': {
|
||||||
|
if (state.isExpanded) return
|
||||||
|
const first = state.blocks.first()
|
||||||
|
if (!first || !first.isVoid) return
|
||||||
|
e.preventDefault()
|
||||||
|
return transform.moveToEndOfPreviousBlock().apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'down': {
|
||||||
|
if (state.isExpanded) return
|
||||||
|
const first = state.blocks.first()
|
||||||
|
if (!first || !first.isVoid) return
|
||||||
|
e.preventDefault()
|
||||||
|
return transform.moveToStartOfNextBlock().apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'left': {
|
||||||
|
if (state.isExpanded) return
|
||||||
|
const node = state.blocks.first() || state.inlines.first()
|
||||||
|
if (!node || !node.isVoid) return
|
||||||
|
e.preventDefault()
|
||||||
|
return transform.moveToEndOfPreviousText().apply()
|
||||||
|
}
|
||||||
|
|
||||||
|
case 'right': {
|
||||||
|
if (state.isExpanded) return
|
||||||
|
const node = state.blocks.first() || state.inlines.first()
|
||||||
|
if (!node || !node.isVoid) return
|
||||||
|
e.preventDefault()
|
||||||
|
return transform.moveToStartOfNextText().apply()
|
||||||
|
}
|
||||||
|
|
||||||
case 'y': {
|
case 'y': {
|
||||||
if (!isWindowsCommand(e)) return
|
if (!isWindowsCommand(e)) return
|
||||||
return transform.redo()
|
return transform.redo()
|
||||||
|
Reference in New Issue
Block a user