1
0
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:
Ian Storm Taylor
2016-06-30 14:37:29 -07:00
parent 1069fee13a
commit c98845e3a0
4 changed files with 219 additions and 0 deletions

View File

@@ -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`.
*

View File

@@ -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
}

View File

@@ -76,6 +76,13 @@ const STATE_TRANSFORMS = [
'insertText',
'mark',
'moveToStartOfPreviousBlock',
'moveToEndOfPreviousBlock',
'moveToStartOfNextBlock',
'moveToEndOfNextBlock',
'moveToStartOfPreviousText',
'moveToEndOfPreviousText',
'moveToStartOfNextText',
'moveToEndOfNextText',
'setBlock',
'setInline',
'splitBlock',

View File

@@ -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()