mirror of
https://github.com/ianstormtaylor/slate.git
synced 2025-07-31 20:40:19 +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)
|
||||
},
|
||||
|
||||
/**
|
||||
* 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`.
|
||||
*
|
||||
|
@@ -557,6 +557,161 @@ class State extends Record(DEFAULTS) {
|
||||
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 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 })
|
||||
return state
|
||||
}
|
||||
|
@@ -76,6 +76,13 @@ const STATE_TRANSFORMS = [
|
||||
'insertText',
|
||||
'mark',
|
||||
'moveToStartOfPreviousBlock',
|
||||
'moveToEndOfPreviousBlock',
|
||||
'moveToStartOfNextBlock',
|
||||
'moveToEndOfNextBlock',
|
||||
'moveToStartOfPreviousText',
|
||||
'moveToEndOfPreviousText',
|
||||
'moveToStartOfNextText',
|
||||
'moveToEndOfNextText',
|
||||
'setBlock',
|
||||
'setInline',
|
||||
'splitBlock',
|
||||
|
@@ -63,6 +63,38 @@ export default {
|
||||
: 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': {
|
||||
if (!isWindowsCommand(e)) return
|
||||
return transform.redo()
|
||||
|
Reference in New Issue
Block a user