diff --git a/packages/slate/src/changes/at-range.js b/packages/slate/src/changes/at-range.js
index c40161a43..cafaf8535 100644
--- a/packages/slate/src/changes/at-range.js
+++ b/packages/slate/src/changes/at-range.js
@@ -948,7 +948,26 @@ Changes.setBlockAtRange = (change, range, properties, options = {}) => {
const { document } = value
const blocks = document.getBlocksAtRange(range)
- blocks.forEach(block => {
+ const { startKey, startOffset, endKey, endOffset, isCollapsed } = range
+ const isStartVoid = document.hasVoidParent(startKey)
+ const startBlock = document.getClosestBlock(startKey)
+ const endBlock = document.getClosestBlock(endKey)
+
+ // Check if we have a "hanging" selection case where the even though the
+ // selection extends into the start of the end node, we actually want to
+ // ignore that for UX reasons.
+ const isHanging =
+ isCollapsed == false &&
+ startOffset == 0 &&
+ endOffset == 0 &&
+ isStartVoid == false &&
+ startKey == startBlock.getFirstText().key &&
+ endKey == endBlock.getFirstText().key
+
+ // If it's a hanging selection, ignore the last block.
+ const sets = isHanging ? blocks.slice(0, -1) : blocks
+
+ sets.forEach(block => {
change.setNodeByKey(block.key, properties, { normalize })
})
}
diff --git a/packages/slate/test/changes/at-current-range/set-block/across-blocks.js b/packages/slate/test/changes/at-current-range/set-block/across-blocks.js
index f8aa5ad34..ea5b47427 100644
--- a/packages/slate/test/changes/at-current-range/set-block/across-blocks.js
+++ b/packages/slate/test/changes/at-current-range/set-block/across-blocks.js
@@ -13,7 +13,7 @@ export const input = (
word
- another
+ another
@@ -26,7 +26,7 @@ export const output = (
word
- another
+ another
diff --git a/packages/slate/test/changes/at-current-range/set-block/hanging-selection.js b/packages/slate/test/changes/at-current-range/set-block/hanging-selection.js
new file mode 100644
index 000000000..08371583c
--- /dev/null
+++ b/packages/slate/test/changes/at-current-range/set-block/hanging-selection.js
@@ -0,0 +1,33 @@
+/** @jsx h */
+
+import h from '../../../helpers/h'
+
+export default function(change) {
+ change.setBlock({ type: 'code' })
+}
+
+export const input = (
+
+
+
+ word
+
+
+ another
+
+
+
+)
+
+export const output = (
+
+
+
+ word
+
+
+ another
+
+
+
+)