From 771e557a904d21c686f1ec97e3716c959d03c6a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ella=20van=C2=A0Durpe?= Date: Mon, 20 Jul 2020 18:26:30 +0300 Subject: [PATCH] Inserter: fix line to show again (#20792) * Inserter: fix line to show again * Fix client id * Split component * Reorganise --- .../components/block-list/insertion-point.js | 214 ++++++++++-------- .../components/block-list/root-container.js | 6 +- .../src/components/block-list/style.scss | 2 +- 3 files changed, 122 insertions(+), 100 deletions(-) diff --git a/packages/block-editor/src/components/block-list/insertion-point.js b/packages/block-editor/src/components/block-list/insertion-point.js index b1cab6c6d5e001..c7eb0e8d6ee80a 100644 --- a/packages/block-editor/src/components/block-list/insertion-point.js +++ b/packages/block-editor/src/components/block-list/insertion-point.js @@ -18,57 +18,139 @@ import Inserter from '../inserter'; import { getClosestTabbable } from '../writing-flow'; import { getBlockDOMNode } from '../../utils/dom'; -function Indicator( { clientId } ) { - const showInsertionPoint = useSelect( +function InsertionPointInserter( { + clientId, + setIsInserterForced, + containerRef, +} ) { + const ref = useRef(); + // Hide the inserter above the selected block and during multi-selection. + const isInserterHidden = useSelect( ( select ) => { const { - getBlockIndex, - getBlockInsertionPoint, - isBlockInsertionPointVisible, - getBlockRootClientId, + getMultiSelectedBlockClientIds, + getSelectedBlockClientId, + hasMultiSelection, } = select( 'core/block-editor' ); - const rootClientId = getBlockRootClientId( clientId ); - const blockIndex = getBlockIndex( clientId, rootClientId ); - const insertionPoint = getBlockInsertionPoint(); - return ( - isBlockInsertionPointVisible() && - insertionPoint.index === blockIndex && - insertionPoint.rootClientId === rootClientId - ); + const multiSelectedBlockClientIds = getMultiSelectedBlockClientIds(); + const selectedBlockClientId = getSelectedBlockClientId(); + + return hasMultiSelection() + ? multiSelectedBlockClientIds.includes( clientId ) + : clientId === selectedBlockClientId; }, [ clientId ] ); - if ( ! showInsertionPoint ) { - return null; + function focusClosestTabbable( event ) { + const { clientX, clientY, target } = event; + + // Only handle click on the wrapper specifically, and not an event + // bubbled from the inserter itself. + if ( target !== ref.current ) { + return; + } + + const targetRect = target.getBoundingClientRect(); + const isReverse = clientY < targetRect.top + targetRect.height / 2; + const blockNode = getBlockDOMNode( clientId ); + const container = isReverse ? containerRef.current : blockNode; + const closest = + getClosestTabbable( blockNode, true, container ) || blockNode; + const rect = new window.DOMRect( clientX, clientY, 0, 16 ); + + placeCaretAtVerticalEdge( closest, isReverse, rect, false ); } return ( -
+ /* eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */ +
setIsInserterForced( true ) } + onBlur={ () => setIsInserterForced( false ) } + onClick={ focusClosestTabbable } + // While ideally it would be enough to capture the + // bubbling focus event from the Inserter, due to the + // characteristics of click focusing of `button`s in + // Firefox and Safari, it is not reliable. + // + // See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus + tabIndex={ -1 } + className={ classnames( + 'block-editor-block-list__insertion-point-inserter', + { + 'is-inserter-hidden': isInserterHidden, + } + ) } + > + +
); } -export default function InsertionPoint( { - hasMultiSelection, - selectedBlockClientId, - children, +function InsertionPointPopover( { + clientId, + isInserterShown, + isInserterForced, + setIsInserterForced, containerRef, + showInsertionPoint, } ) { + const element = getBlockDOMNode( clientId ); + + return ( + +
+ { showInsertionPoint && ( +
+ ) } + { ( isInserterShown || isInserterForced ) && ( + + ) } +
+ + ); +} + +export default function InsertionPoint( { children, containerRef } ) { const [ isInserterShown, setIsInserterShown ] = useState( false ); const [ isInserterForced, setIsInserterForced ] = useState( false ); - const [ inserterElement, setInserterElement ] = useState( null ); const [ inserterClientId, setInserterClientId ] = useState( null ); - const ref = useRef(); - const { multiSelectedBlockClientIds, isMultiSelecting } = useSelect( + const { isMultiSelecting, isInserterVisible, selectedClientId } = useSelect( ( select ) => { const { - getMultiSelectedBlockClientIds, isMultiSelecting: _isMultiSelecting, + isBlockInsertionPointVisible, + getBlockInsertionPoint, + getBlockOrder, } = select( 'core/block-editor' ); + const insertionPoint = getBlockInsertionPoint(); + const order = getBlockOrder( insertionPoint.rootClientId ); + return { isMultiSelecting: _isMultiSelecting(), - multiSelectedBlockClientIds: getMultiSelectedBlockClientIds(), + isInserterVisible: isBlockInsertionPointVisible(), + selectedClientId: order[ insertionPoint.index ], }; }, [] @@ -117,80 +199,24 @@ export default function InsertionPoint( { } setIsInserterShown( true ); - setInserterElement( element ); setInserterClientId( clientId ); } - function focusClosestTabbable( event ) { - const { clientX, clientY, target } = event; - - // Only handle click on the wrapper specifically, and not an event - // bubbled from the inserter itself. - if ( target !== ref.current ) { - return; - } - - const targetRect = target.getBoundingClientRect(); - const isReverse = clientY < targetRect.top + targetRect.height / 2; - const blockNode = getBlockDOMNode( inserterClientId ); - const container = isReverse ? containerRef.current : blockNode; - const closest = - getClosestTabbable( blockNode, true, container ) || blockNode; - const rect = new window.DOMRect( clientX, clientY, 0, 16 ); - - placeCaretAtVerticalEdge( closest, isReverse, rect, false ); - } - - // Hide the inserter above the selected block and during multi-selection. - const isInserterHidden = hasMultiSelection - ? multiSelectedBlockClientIds.includes( inserterClientId ) - : inserterClientId === selectedBlockClientId; + const isVisible = isInserterShown || isInserterForced || isInserterVisible; return ( <> - { ! isMultiSelecting && ( isInserterShown || isInserterForced ) && ( - -
- - { /* eslint-disable-next-line jsx-a11y/no-static-element-interactions, jsx-a11y/click-events-have-key-events */ } -
setIsInserterForced( true ) } - onBlur={ () => setIsInserterForced( false ) } - onClick={ focusClosestTabbable } - // While ideally it would be enough to capture the - // bubbling focus event from the Inserter, due to the - // characteristics of click focusing of `button`s in - // Firefox and Safari, it is not reliable. - // - // See: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus - tabIndex={ -1 } - className={ classnames( - 'block-editor-block-list__insertion-point-inserter', - { - 'is-inserter-hidden': isInserterHidden, - } - ) } - > - -
-
-
+ { ! isMultiSelecting && isVisible && ( + ) }
+