@@ -13,6 +13,7 @@ import { Component, findDOMNode, compose } from '@wordpress/element';
13
13
import {
14
14
keycodes ,
15
15
focus ,
16
+ isTextField ,
16
17
placeCaretAtHorizontalEdge ,
17
18
placeCaretAtVerticalEdge ,
18
19
} from '@wordpress/utils' ;
@@ -53,8 +54,6 @@ import {
53
54
removeBlock ,
54
55
replaceBlocks ,
55
56
selectBlock ,
56
- startTyping ,
57
- stopTyping ,
58
57
updateBlockAttributes ,
59
58
toggleSelection ,
60
59
} from '../../store/actions' ;
@@ -75,7 +74,7 @@ import {
75
74
getSelectedBlocksInitialCaretPosition ,
76
75
} from '../../store/selectors' ;
77
76
78
- const { BACKSPACE , ESCAPE , DELETE , ENTER , UP , RIGHT , DOWN , LEFT } = keycodes ;
77
+ const { BACKSPACE , DELETE , ENTER } = keycodes ;
79
78
80
79
export class BlockListBlock extends Component {
81
80
constructor ( ) {
@@ -86,25 +85,21 @@ export class BlockListBlock extends Component {
86
85
this . setAttributes = this . setAttributes . bind ( this ) ;
87
86
this . maybeHover = this . maybeHover . bind ( this ) ;
88
87
this . hideHoverEffects = this . hideHoverEffects . bind ( this ) ;
89
- this . maybeStartTyping = this . maybeStartTyping . bind ( this ) ;
90
- this . stopTypingOnMouseMove = this . stopTypingOnMouseMove . bind ( this ) ;
91
88
this . mergeBlocks = this . mergeBlocks . bind ( this ) ;
92
89
this . onFocus = this . onFocus . bind ( this ) ;
93
90
this . preventDrag = this . preventDrag . bind ( this ) ;
94
91
this . onPointerDown = this . onPointerDown . bind ( this ) ;
95
- this . onKeyDown = this . onKeyDown . bind ( this ) ;
92
+ this . deleteOrInsertAfterWrapper = this . deleteOrInsertAfterWrapper . bind ( this ) ;
96
93
this . onBlockError = this . onBlockError . bind ( this ) ;
97
94
this . insertBlocksAfter = this . insertBlocksAfter . bind ( this ) ;
98
95
this . onTouchStart = this . onTouchStart . bind ( this ) ;
99
96
this . onClick = this . onClick . bind ( this ) ;
100
97
this . selectOnOpen = this . selectOnOpen . bind ( this ) ;
101
- this . onSelectionChange = this . onSelectionChange . bind ( this ) ;
102
98
this . hadTouchStart = false ;
103
99
104
100
this . state = {
105
101
error : null ,
106
102
isHovered : false ,
107
- isSelectionCollapsed : true ,
108
103
} ;
109
104
}
110
105
@@ -126,46 +121,23 @@ export class BlockListBlock extends Component {
126
121
}
127
122
128
123
componentDidMount ( ) {
129
- if ( this . props . isTyping ) {
130
- document . addEventListener ( 'mousemove' , this . stopTypingOnMouseMove ) ;
131
- }
132
- document . addEventListener ( 'selectionchange' , this . onSelectionChange ) ;
133
-
134
124
if ( this . props . isSelected ) {
135
125
this . focusTabbable ( ) ;
136
126
}
137
127
}
138
128
139
129
componentWillReceiveProps ( newProps ) {
140
- if ( newProps . isTyping || newProps . isSelected ) {
130
+ if ( newProps . isTypingWithinBlock || newProps . isSelected ) {
141
131
this . hideHoverEffects ( ) ;
142
132
}
143
133
}
144
134
145
135
componentDidUpdate ( prevProps ) {
146
- // Bind or unbind mousemove from page when user starts or stops typing
147
- if ( this . props . isTyping !== prevProps . isTyping ) {
148
- if ( this . props . isTyping ) {
149
- document . addEventListener ( 'mousemove' , this . stopTypingOnMouseMove ) ;
150
- } else {
151
- this . removeStopTypingListener ( ) ;
152
- }
153
- }
154
-
155
136
if ( this . props . isSelected && ! prevProps . isSelected ) {
156
137
this . focusTabbable ( ) ;
157
138
}
158
139
}
159
140
160
- componentWillUnmount ( ) {
161
- this . removeStopTypingListener ( ) ;
162
- document . removeEventListener ( 'selectionchange' , this . onSelectionChange ) ;
163
- }
164
-
165
- removeStopTypingListener ( ) {
166
- document . removeEventListener ( 'mousemove' , this . stopTypingOnMouseMove ) ;
167
- }
168
-
169
141
setBlockListRef ( node ) {
170
142
// Disable reason: The root return element uses a component to manage
171
143
// event nesting, but the parent block list layout needs the raw DOM
@@ -202,15 +174,15 @@ export class BlockListBlock extends Component {
202
174
}
203
175
204
176
// Find all tabbables within node.
205
- const tabbables = focus . tabbable . find ( this . node )
206
- . filter ( ( node ) => node !== this . node ) ;
177
+ const textInputs = focus . tabbable . find ( this . node ) . filter ( isTextField ) ;
207
178
208
179
// If reversed (e.g. merge via backspace), use the last in the set of
209
180
// tabbables.
210
181
const isReverse = - 1 === initialPosition ;
211
- const target = ( isReverse ? last : first ) ( tabbables ) ;
182
+ const target = ( isReverse ? last : first ) ( textInputs ) ;
212
183
213
184
if ( ! target ) {
185
+ this . wrapperNode . focus ( ) ;
214
186
return ;
215
187
}
216
188
@@ -297,31 +269,6 @@ export class BlockListBlock extends Component {
297
269
}
298
270
}
299
271
300
- maybeStartTyping ( ) {
301
- // We do not want to dispatch start typing if state value already reflects
302
- // that we're typing (dispatch noise)
303
- if ( ! this . props . isTyping ) {
304
- this . props . onStartTyping ( ) ;
305
- }
306
- }
307
-
308
- stopTypingOnMouseMove ( { clientX, clientY } ) {
309
- const { lastClientX, lastClientY } = this ;
310
-
311
- // We need to check that the mouse really moved
312
- // Because Safari trigger mousemove event when we press shift, ctrl...
313
- if (
314
- lastClientX &&
315
- lastClientY &&
316
- ( lastClientX !== clientX || lastClientY !== clientY )
317
- ) {
318
- this . props . onStopTyping ( ) ;
319
- }
320
-
321
- this . lastClientX = clientX ;
322
- this . lastClientY = clientY ;
323
- }
324
-
325
272
mergeBlocks ( forward = false ) {
326
273
const { block, previousBlockUid, nextBlockUid, onMerge } = this . props ;
327
274
@@ -338,10 +285,6 @@ export class BlockListBlock extends Component {
338
285
} else {
339
286
onMerge ( previousBlockUid , block . uid ) ;
340
287
}
341
-
342
- // Manually trigger typing mode, since merging will remove this block and
343
- // cause onKeyDown to not fire
344
- this . maybeStartTyping ( ) ;
345
288
}
346
289
347
290
insertBlocksAfter ( blocks ) {
@@ -406,56 +349,41 @@ export class BlockListBlock extends Component {
406
349
}
407
350
}
408
351
409
- onKeyDown ( event ) {
352
+ /**
353
+ * Interprets keydown event intent to remove or insert after block if key
354
+ * event occurs on wrapper node. This can occur when the block has no text
355
+ * fields of its own, particularly after initial insertion, to allow for
356
+ * easy deletion and continuous writing flow to add additional content.
357
+ *
358
+ * @param {KeyboardEvent } event Keydown event.
359
+ */
360
+ deleteOrInsertAfterWrapper ( event ) {
410
361
const { keyCode, target } = event ;
411
362
363
+ if ( target !== this . wrapperNode || this . props . isLocked ) {
364
+ return ;
365
+ }
366
+
412
367
switch ( keyCode ) {
413
368
case ENTER :
414
369
// Insert default block after current block if enter and event
415
370
// not already handled by descendant.
416
- if ( target === this . node && ! this . props . isLocked ) {
417
- event . preventDefault ( ) ;
418
-
419
- this . props . onInsertBlocks ( [
420
- createBlock ( 'core/paragraph' ) ,
421
- ] , this . props . order + 1 ) ;
422
- }
423
-
424
- // Pressing enter should trigger typing mode after the content has split
425
- this . maybeStartTyping ( ) ;
426
- break ;
427
-
428
- case UP :
429
- case RIGHT :
430
- case DOWN :
431
- case LEFT :
432
- // Arrow keys do not fire keypress event, but should still
433
- // trigger typing mode.
434
- this . maybeStartTyping ( ) ;
371
+ this . props . onInsertBlocks ( [
372
+ createBlock ( 'core/paragraph' ) ,
373
+ ] , this . props . order + 1 ) ;
374
+ event . preventDefault ( ) ;
435
375
break ;
436
376
437
377
case BACKSPACE :
438
378
case DELETE :
439
379
// Remove block on backspace.
440
- if ( target === this . node ) {
441
- const { uid, onRemove, isLocked, previousBlock, onSelect } = this . props ;
442
- event . preventDefault ( ) ;
443
- if ( ! isLocked ) {
444
- onRemove ( uid ) ;
445
-
446
- if ( previousBlock ) {
447
- onSelect ( previousBlock . uid , - 1 ) ;
448
- }
449
- }
450
- }
451
-
452
- // Pressing backspace should trigger typing mode
453
- this . maybeStartTyping ( ) ;
454
- break ;
380
+ const { uid, onRemove, previousBlockUid, onSelect } = this . props ;
381
+ onRemove ( uid ) ;
455
382
456
- case ESCAPE :
457
- // Deselect on escape.
458
- this . props . onDeselect ( ) ;
383
+ if ( previousBlockUid ) {
384
+ onSelect ( previousBlockUid , - 1 ) ;
385
+ }
386
+ event . preventDefault ( ) ;
459
387
break ;
460
388
}
461
389
}
@@ -470,19 +398,6 @@ export class BlockListBlock extends Component {
470
398
}
471
399
}
472
400
473
- onSelectionChange ( ) {
474
- if ( ! this . props . isSelected ) {
475
- return ;
476
- }
477
-
478
- const selection = window . getSelection ( ) ;
479
- const isCollapsed = selection . rangeCount > 0 && selection . getRangeAt ( 0 ) . collapsed ;
480
- // We only keep track of the collapsed selection for selected blocks.
481
- if ( isCollapsed !== this . state . isSelectionCollapsed && this . props . isSelected ) {
482
- this . setState ( { isSelectionCollapsed : isCollapsed } ) ;
483
- }
484
- }
485
-
486
401
render ( ) {
487
402
const {
488
403
block,
@@ -499,6 +414,7 @@ export class BlockListBlock extends Component {
499
414
isMultiSelected,
500
415
isFirstMultiSelected,
501
416
isLastInSelection,
417
+ isTypingWithinBlock,
502
418
} = this . props ;
503
419
const isHovered = this . state . isHovered && ! this . props . isMultiSelecting ;
504
420
const { name : blockName , isValid } = block ;
@@ -508,11 +424,11 @@ export class BlockListBlock extends Component {
508
424
// The block as rendered in the editor is composed of general block UI
509
425
// (mover, toolbar, wrapper) and the display of the block content.
510
426
511
- // If the block is selected and we're typing the block should not appear as selected unless the selection is not collapsed .
427
+ // If the block is selected and we're typing the block should not appear.
512
428
// Empty paragraph blocks should always show up as unselected.
513
429
const isEmptyDefaultBlock = isUnmodifiedDefaultBlock ( block ) ;
430
+ const isSelectedNotTyping = isSelected && ! isTypingWithinBlock ;
514
431
const showSideInserter = ( isSelected || isHovered ) && isEmptyDefaultBlock ;
515
- const isSelectedNotTyping = isSelected && ( ! this . props . isTyping || ! this . state . isSelectionCollapsed ) ;
516
432
const shouldAppearSelected = ! showSideInserter && isSelectedNotTyping ;
517
433
const shouldShowMovers = shouldAppearSelected || isHovered || ( isEmptyDefaultBlock && isSelectedNotTyping ) ;
518
434
const shouldShowSettingsMenu = shouldShowMovers ;
@@ -568,12 +484,11 @@ export class BlockListBlock extends Component {
568
484
onTouchStart = { this . onTouchStart }
569
485
onFocus = { this . onFocus }
570
486
onClick = { this . onClick }
487
+ onKeyDown = { this . deleteOrInsertAfterWrapper }
571
488
tabIndex = "0"
572
489
childHandledEvents = { [
573
- 'onKeyPress' ,
574
490
'onDragStart' ,
575
491
'onMouseDown' ,
576
- 'onKeyDown' ,
577
492
] }
578
493
{ ...wrapperProps }
579
494
>
@@ -602,10 +517,8 @@ export class BlockListBlock extends Component {
602
517
{ isFirstMultiSelected && < BlockMultiControls rootUID = { rootUID } /> }
603
518
< IgnoreNestedEvents
604
519
ref = { this . bindBlockNode }
605
- onKeyPress = { this . maybeStartTyping }
606
520
onDragStart = { this . preventDrag }
607
521
onMouseDown = { this . onPointerDown }
608
- onKeyDown = { this . onKeyDown }
609
522
className = "editor-block-list__block-edit"
610
523
aria-label = { blockLabel }
611
524
data-block = { block . uid }
@@ -677,7 +590,7 @@ const mapStateToProps = ( state, { uid, rootUID } ) => {
677
590
isLastInSelection : state . blockSelection . end === uid ,
678
591
// We only care about this prop when the block is selected
679
592
// Thus to avoid unnecessary rerenders we avoid updating the prop if the block is not selected.
680
- isTyping : isSelected && isTyping ( state ) ,
593
+ isTypingWithinBlock : isSelected && isTyping ( state ) ,
681
594
order : getBlockIndex ( state , uid , rootUID ) ,
682
595
meta : getEditedPostAttribute ( state , 'meta' ) ,
683
596
mode : getBlockMode ( state , uid ) ,
@@ -701,14 +614,6 @@ const mapDispatchToProps = ( dispatch, ownProps ) => ( {
701
614
dispatch ( clearSelectedBlock ( ) ) ;
702
615
} ,
703
616
704
- onStartTyping ( ) {
705
- dispatch ( startTyping ( ) ) ;
706
- } ,
707
-
708
- onStopTyping ( ) {
709
- dispatch ( stopTyping ( ) ) ;
710
- } ,
711
-
712
617
onInsertBlocks ( blocks , index ) {
713
618
const { rootUID, layout } = ownProps ;
714
619
0 commit comments