@@ -3,10 +3,13 @@ import {isTextBlock} from '@portabletext/schema'
33import { defaultKeyboardShortcuts } from '../keyboard-shortcuts/default-keyboard-shortcuts'
44import { getFocusBlock } from '../selectors/selector.get-focus-block'
55import { getFocusInlineObject } from '../selectors/selector.get-focus-inline-object'
6+ import { getFocusTextBlock } from '../selectors/selector.get-focus-text-block'
7+ import { getNextBlock } from '../selectors/selector.get-next-block'
68import { getPreviousBlock } from '../selectors/selector.get-previous-block'
79import { isSelectionCollapsed } from '../selectors/selector.is-selection-collapsed'
810import { isSelectionExpanded } from '../selectors/selector.is-selection-expanded'
911import { getBlockEndPoint } from '../utils/util.get-block-end-point'
12+ import { getBlockStartPoint } from '../utils/util.get-block-start-point'
1013import { isEmptyTextBlock } from '../utils/util.is-empty-text-block'
1114import { raise } from './behavior.types.action'
1215import { defineBehavior } from './behavior.types.behavior'
@@ -22,6 +25,17 @@ const shiftLeft = createKeyboardShortcut({
2225 } ,
2326 ] ,
2427} )
28+ const shiftDown = createKeyboardShortcut ( {
29+ default : [
30+ {
31+ key : 'ArrowDown' ,
32+ shift : true ,
33+ meta : false ,
34+ ctrl : false ,
35+ alt : false ,
36+ } ,
37+ ] ,
38+ } )
2539
2640export const abstractKeyboardBehaviors = [
2741 /**
@@ -171,4 +185,93 @@ export const abstractKeyboardBehaviors = [
171185 ] ,
172186 ] ,
173187 } ) ,
188+
189+ defineBehavior ( {
190+ on : 'keyboard.keydown' ,
191+ guard : ( { snapshot, event, dom} ) => {
192+ if ( ! snapshot . context . selection || ! shiftDown . guard ( event . originEvent ) ) {
193+ return false
194+ }
195+
196+ const focusTextBlock = getFocusTextBlock ( snapshot )
197+
198+ if ( ! focusTextBlock ) {
199+ return false
200+ }
201+
202+ const nextBlock = getNextBlock ( snapshot )
203+
204+ if ( ! nextBlock ) {
205+ return false
206+ }
207+
208+ if ( ! isTextBlock ( snapshot . context , nextBlock . node ) ) {
209+ return false
210+ }
211+
212+ const focusBlockEndPoint = getBlockEndPoint ( {
213+ context : snapshot . context ,
214+ block : focusTextBlock ,
215+ } )
216+
217+ // Find the DOM position of the current focus point
218+ const focusRect = dom . getSelectionRect ( {
219+ ...snapshot ,
220+ context : {
221+ ...snapshot . context ,
222+ selection : {
223+ anchor : snapshot . context . selection . focus ,
224+ focus : snapshot . context . selection . focus ,
225+ } ,
226+ } ,
227+ } )
228+ // Find the DOM position of the focus block end point
229+ const endPointRect = dom . getSelectionRect ( {
230+ ...snapshot ,
231+ context : {
232+ ...snapshot . context ,
233+ selection : {
234+ anchor : focusBlockEndPoint ,
235+ focus : focusBlockEndPoint ,
236+ } ,
237+ } ,
238+ } )
239+
240+ if ( ! focusRect || ! endPointRect ) {
241+ return false
242+ }
243+
244+ if ( endPointRect . top > focusRect . top ) {
245+ // If the end point is positioned further from the top than the current
246+ // focus point, then we can deduce that the end point is on the next
247+ // line. In this case, we don't want to interfere since the browser
248+ // does right thing and expands the selection to the end of the current
249+ // line.
250+ return false
251+ }
252+
253+ // If the end point is positioned at the same level as the current focus
254+ // point, then we can deduce that the end point is on the same line. In
255+ // this case, we want to expand the selection to the end of the start
256+ // block. This mitigates a Chromium bug where Shift+ArrowDown can expand
257+ // further into the next block.
258+ const nextBlockStartPoint = getBlockStartPoint ( {
259+ context : snapshot . context ,
260+ block : nextBlock ,
261+ } )
262+
263+ return { nextBlockStartPoint, selection : snapshot . context . selection }
264+ } ,
265+ actions : [
266+ ( _ , { nextBlockStartPoint, selection} ) => [
267+ raise ( {
268+ type : 'select' ,
269+ at : {
270+ anchor : selection . anchor ,
271+ focus : nextBlockStartPoint ,
272+ } ,
273+ } ) ,
274+ ] ,
275+ ] ,
276+ } ) ,
174277]
0 commit comments