From ec5daeb5284ad54640d67b85a2f51058535b7a64 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Thu, 8 Jul 2021 16:48:06 +0800 Subject: [PATCH 01/16] Enable list view --- .../block-editor/src/components/list-view/block-contents.js | 6 +++--- packages/block-editor/src/components/list-view/index.js | 6 +----- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/list-view/block-contents.js b/packages/block-editor/src/components/list-view/block-contents.js index 99ccc7907da441..9ae49dfdea4e34 100644 --- a/packages/block-editor/src/components/list-view/block-contents.js +++ b/packages/block-editor/src/components/list-view/block-contents.js @@ -34,7 +34,7 @@ const ListViewBlockContents = forwardRef( ) => { const { __experimentalFeatures, - blockDropTarget = {}, + blockDropTarget, } = useListViewContext(); const { clientId } = block; @@ -66,7 +66,7 @@ const ListViewBlockContents = forwardRef( rootClientId: dropTargetRootClientId, clientId: dropTargetClientId, dropPosition, - } = blockDropTarget; + } = blockDropTarget || {}; const isDroppingBefore = dropTargetRootClientId === rootClientId && @@ -117,7 +117,7 @@ const ListViewBlockContents = forwardRef( position={ position } siblingBlockCount={ siblingBlockCount } level={ level } - draggable={ draggable && __experimentalFeatures } + draggable={ draggable } onDragStart={ onDragStart } onDragEnd={ onDragEnd } { ...props } diff --git a/packages/block-editor/src/components/list-view/index.js b/packages/block-editor/src/components/list-view/index.js index c3a090c5c52099..abfa891ed3e693 100644 --- a/packages/block-editor/src/components/list-view/index.js +++ b/packages/block-editor/src/components/list-view/index.js @@ -70,17 +70,13 @@ export default function ListView( { ); const [ expandedState, setExpandedState ] = useReducer( expanded, {} ); - let { ref: treeGridRef, target: blockDropTarget } = useListViewDropZone(); + const { ref: treeGridRef, target: blockDropTarget } = useListViewDropZone(); const isMounted = useRef( false ); useEffect( () => { isMounted.current = true; }, [] ); - if ( ! __experimentalFeatures ) { - blockDropTarget = undefined; - } - const expand = ( clientId ) => { if ( ! clientId ) { return; From 22f841f9ab0244c3656d701f1ed7cef52a9e5c90 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Thu, 8 Jul 2021 19:22:21 +0800 Subject: [PATCH 02/16] Use drop indicator component instead of borders --- .../components/list-view/block-contents.js | 32 +------ .../components/list-view/drop-indicator.js | 91 +++++++++++++++++++ .../src/components/list-view/index.js | 27 +++--- .../src/components/list-view/style.scss | 31 ++----- 4 files changed, 119 insertions(+), 62 deletions(-) create mode 100644 packages/block-editor/src/components/list-view/drop-indicator.js diff --git a/packages/block-editor/src/components/list-view/block-contents.js b/packages/block-editor/src/components/list-view/block-contents.js index 9ae49dfdea4e34..18215ecfba6b4b 100644 --- a/packages/block-editor/src/components/list-view/block-contents.js +++ b/packages/block-editor/src/components/list-view/block-contents.js @@ -32,18 +32,11 @@ const ListViewBlockContents = forwardRef( }, ref ) => { - const { - __experimentalFeatures, - blockDropTarget, - } = useListViewContext(); + const { __experimentalFeatures } = useListViewContext(); const { clientId } = block; - const { - rootClientId, - blockMovingClientId, - selectedBlockInBlockEditor, - } = useSelect( + const { blockMovingClientId, selectedBlockInBlockEditor } = useSelect( ( select ) => { const { getBlockRootClientId, @@ -62,27 +55,8 @@ const ListViewBlockContents = forwardRef( const isBlockMoveTarget = blockMovingClientId && selectedBlockInBlockEditor === clientId; - const { - rootClientId: dropTargetRootClientId, - clientId: dropTargetClientId, - dropPosition, - } = blockDropTarget || {}; - - const isDroppingBefore = - dropTargetRootClientId === rootClientId && - dropTargetClientId === clientId && - dropPosition === 'top'; - const isDroppingAfter = - dropTargetRootClientId === rootClientId && - dropTargetClientId === clientId && - dropPosition === 'bottom'; - const isDroppingToInnerBlocks = - dropTargetRootClientId === clientId && dropPosition === 'inside'; - const className = classnames( 'block-editor-list-view-block-contents', { - 'is-dropping-before': isDroppingBefore || isBlockMoveTarget, - 'is-dropping-after': isDroppingAfter, - 'is-dropping-to-inner-blocks': isDroppingToInnerBlocks, + 'is-dropping-before': isBlockMoveTarget, } ); return ( diff --git a/packages/block-editor/src/components/list-view/drop-indicator.js b/packages/block-editor/src/components/list-view/drop-indicator.js new file mode 100644 index 00000000000000..f3dcc1775690f4 --- /dev/null +++ b/packages/block-editor/src/components/list-view/drop-indicator.js @@ -0,0 +1,91 @@ +/** + * WordPress dependencies + */ +import { Popover } from '@wordpress/components'; +import { useCallback, useMemo } from '@wordpress/element'; + +/** + * Internal dependencies + */ +import { useListViewContext } from './context'; + +export default function ListViewDropIndicator( { listViewRef } ) { + const { blockDropTarget } = useListViewContext(); + + const { clientId, dropPosition } = blockDropTarget || {}; + + const blockElement = useMemo( () => { + if ( ! clientId || ! listViewRef.current ) { + return; + } + + return listViewRef.current.ownerDocument.getElementById( + `list-view-block-${ clientId }` + ); + }, [ clientId ] ); + + const style = useMemo( () => { + if ( ! blockElement ) { + return {}; + } + + return { + width: blockElement.offsetWidth, + }; + }, [ blockElement ] ); + + const getAnchorRect = useCallback( () => { + if ( ! blockElement ) { + return {}; + } + + const ownerDocument = blockElement.ownerDocument; + const rect = blockElement.getBoundingClientRect(); + + if ( dropPosition === 'top' ) { + return { + top: rect.top - 2, + bottom: rect.top, + left: rect.left, + right: rect.right, + width: rect.width, + height: rect.height, + ownerDocument, + }; + } + + if ( dropPosition === 'bottom' || dropPosition === 'inside' ) { + return { + top: rect.bottom, + bottom: rect.bottom + 2, + left: rect.left, + right: rect.right, + width: rect.width, + height: rect.height, + ownerDocument, + }; + } + + return {}; + }, [ blockElement, dropPosition ] ); + + if ( ! clientId ) { + return null; + } + + return ( + +
+ + ); +} diff --git a/packages/block-editor/src/components/list-view/index.js b/packages/block-editor/src/components/list-view/index.js index abfa891ed3e693..3945351388966b 100644 --- a/packages/block-editor/src/components/list-view/index.js +++ b/packages/block-editor/src/components/list-view/index.js @@ -2,6 +2,7 @@ * WordPress dependencies */ +import { useMergeRefs } from '@wordpress/compose'; import { __experimentalTreeGrid as TreeGrid } from '@wordpress/components'; import { useDispatch } from '@wordpress/data'; import { @@ -18,6 +19,7 @@ import { __ } from '@wordpress/i18n'; */ import ListViewBranch from './branch'; import { ListViewContext } from './context'; +import ListViewDropIndicator from './drop-indicator'; import useListViewClientIds from './use-list-view-client-ids'; import useListViewDropZone from './use-list-view-drop-zone'; import { store as blockEditorStore } from '../../store'; @@ -70,7 +72,9 @@ export default function ListView( { ); const [ expandedState, setExpandedState ] = useReducer( expanded, {} ); - const { ref: treeGridRef, target: blockDropTarget } = useListViewDropZone(); + const { ref: dropZoneRef, target: blockDropTarget } = useListViewDropZone(); + const elementRef = useRef(); + const treeGridRef = useMergeRefs( [ elementRef, dropZoneRef ] ); const isMounted = useRef( false ); useEffect( () => { @@ -118,21 +122,22 @@ export default function ListView( { ); return ( - - + + + - - + + ); } diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss index 2c747b5309aadc..5e542d3eb6344e 100644 --- a/packages/block-editor/src/components/list-view/style.scss +++ b/packages/block-editor/src/components/list-view/style.scss @@ -80,28 +80,6 @@ border-top: 4px solid var(--wp-admin-theme-color); } - &.is-dropping-after::before { - content: ""; - position: absolute; - pointer-events: none; - transition: border-color 0.1s linear, border-style 0.1s linear, box-shadow 0.1s linear; - bottom: -2px; - right: 0; - left: 0; - border-bottom: 4px solid var(--wp-admin-theme-color); - } - - &.is-dropping-to-inner-blocks::before { - content: ""; - position: absolute; - pointer-events: none; - transition: border-color 0.1s linear, border-style 0.1s linear, box-shadow 0.1s linear; - bottom: -2px; - right: 0; - left: $icon-size; - border-bottom: 4px solid var(--wp-admin-theme-color); - } - .components-modal__content & { padding-left: 0; padding-right: 0; @@ -318,3 +296,12 @@ $block-navigation-max-indent: 8; transition: transform 0.2s ease; @include reduce-motion("transition"); } + +.block-editor-list-view-drop-indicator { + pointer-events: none; + + .block-editor-list-view-drop-indicator__line { + background: var(--wp-admin-theme-color); + height: 2px; + } +} From 639de9896d929519408ad844cce65c54da8ff652 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 9 Jul 2021 11:38:27 +0800 Subject: [PATCH 03/16] Adjust positioning --- .../src/components/list-view/drop-indicator.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/packages/block-editor/src/components/list-view/drop-indicator.js b/packages/block-editor/src/components/list-view/drop-indicator.js index f3dcc1775690f4..3773ed0389a85d 100644 --- a/packages/block-editor/src/components/list-view/drop-indicator.js +++ b/packages/block-editor/src/components/list-view/drop-indicator.js @@ -44,11 +44,11 @@ export default function ListViewDropIndicator( { listViewRef } ) { if ( dropPosition === 'top' ) { return { - top: rect.top - 2, + top: rect.top, bottom: rect.top, left: rect.left, right: rect.right, - width: rect.width, + width: 0, height: rect.height, ownerDocument, }; @@ -57,10 +57,10 @@ export default function ListViewDropIndicator( { listViewRef } ) { if ( dropPosition === 'bottom' || dropPosition === 'inside' ) { return { top: rect.bottom, - bottom: rect.bottom + 2, + bottom: rect.bottom, left: rect.left, right: rect.right, - width: rect.width, + width: 0, height: rect.height, ownerDocument, }; @@ -79,7 +79,6 @@ export default function ListViewDropIndicator( { listViewRef } ) { animate={ false } getAnchorRect={ getAnchorRect } focusOnMount={ false } - // position="bottom middle" className="block-editor-list-view-drop-indicator" >
Date: Fri, 9 Jul 2021 11:39:39 +0800 Subject: [PATCH 04/16] Unset other styles that interfere with the drop indicator --- .../src/components/list-view/style.scss | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/list-view/style.scss b/packages/block-editor/src/components/list-view/style.scss index 5e542d3eb6344e..610edb31d7b1c4 100644 --- a/packages/block-editor/src/components/list-view/style.scss +++ b/packages/block-editor/src/components/list-view/style.scss @@ -18,11 +18,22 @@ &.is-selected .block-editor-list-view-block-contents { background: var(--wp-admin-theme-color); color: $white; + + // Hide selection styles while a user is dragging blocks/files etc. + .is-dragging-components-draggable & { + background: none; + color: $gray-900; + } } &.is-selected .block-editor-list-view-block-contents:focus { box-shadow: inset 0 0 0 1px $white, 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + + // Hide focus styles while a user is dragging blocks/files etc. + .is-dragging-components-draggable & { + box-shadow: none; + } } &.is-branch-selected.is-selected .block-editor-list-view-block-contents { @@ -64,6 +75,11 @@ &:hover, &:focus { box-shadow: inset 0 0 0 var(--wp-admin-border-width-focus) var(--wp-admin-theme-color); + + // Hide hover styles while a user is dragging blocks/files etc. + .is-dragging-components-draggable & { + box-shadow: none; + } } &:focus { z-index: 1; @@ -302,6 +318,14 @@ $block-navigation-max-indent: 8; .block-editor-list-view-drop-indicator__line { background: var(--wp-admin-theme-color); - height: 2px; + height: $border-width; } } + +// Reset some popover defaults for the drop indicator. +.block-editor-list-view-drop-indicator:not([data-y-axis="middle"][data-x-axis="right"]) > .components-popover__content { + margin-left: 0; + border: none; + box-shadow: none; +} + From 84866685ae16b07bf8940981c14d59704a3c34c2 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 9 Jul 2021 12:07:10 +0800 Subject: [PATCH 05/16] Fix isDropBlock detection --- .../src/components/list-view/use-list-view-drop-zone.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js b/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js index b3e25752ab7dff..98e44a049030fa 100644 --- a/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js +++ b/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js @@ -210,7 +210,9 @@ export default function useListViewDropZone() { const throttled = useThrottle( useCallback( ( event, currentTarget ) => { const position = { x: event.clientX, y: event.clientY }; - const isBlockDrag = !! event.dataTransfer.getData( 'wp-blocks' ); + const isBlockDrag = !! event.dataTransfer.types.includes( + 'wp-blocks' + ); const draggedBlockClientIds = isBlockDrag ? getDraggedBlockClientIds() From 18b967aa6eebde3f660c9454f35c184f56dfaf5a Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 9 Jul 2021 12:19:40 +0800 Subject: [PATCH 06/16] Fix flickering when nesting --- .../list-view/use-list-view-drop-zone.js | 76 ++++++++++--------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js b/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js index 98e44a049030fa..f7b1347acd39d8 100644 --- a/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js +++ b/packages/block-editor/src/components/list-view/use-list-view-drop-zone.js @@ -207,49 +207,51 @@ export default function useListViewDropZone() { target || {}; const onBlockDrop = useOnBlockDrop( targetRootClientId, targetBlockIndex ); - const throttled = useThrottle( - useCallback( ( event, currentTarget ) => { - const position = { x: event.clientX, y: event.clientY }; - const isBlockDrag = !! event.dataTransfer.types.includes( - 'wp-blocks' - ); - const draggedBlockClientIds = isBlockDrag - ? getDraggedBlockClientIds() - : undefined; + const draggedBlockClientIds = getDraggedBlockClientIds(); + const throttled = useThrottle( + useCallback( + ( event, currentTarget ) => { + const position = { x: event.clientX, y: event.clientY }; + const isBlockDrag = !! draggedBlockClientIds?.length; - const blockElements = Array.from( - currentTarget.querySelectorAll( '[data-block]' ) - ); + const blockElements = Array.from( + currentTarget.querySelectorAll( '[data-block]' ) + ); - const blocksData = blockElements.map( ( blockElement ) => { - const clientId = blockElement.dataset.block; - const rootClientId = getBlockRootClientId( clientId ); + const blocksData = blockElements.map( ( blockElement ) => { + const clientId = blockElement.dataset.block; + const rootClientId = getBlockRootClientId( clientId ); - return { - clientId, - rootClientId, - blockIndex: getBlockIndex( clientId, rootClientId ), - element: blockElement, - isDraggedBlock: isBlockDrag - ? draggedBlockClientIds.includes( clientId ) - : false, - innerBlockCount: getBlockCount( clientId ), - canInsertDraggedBlocksAsSibling: isBlockDrag - ? canInsertBlocks( draggedBlockClientIds, rootClientId ) - : true, - canInsertDraggedBlocksAsChild: isBlockDrag - ? canInsertBlocks( draggedBlockClientIds, clientId ) - : true, - }; - } ); + return { + clientId, + rootClientId, + blockIndex: getBlockIndex( clientId, rootClientId ), + element: blockElement, + isDraggedBlock: isBlockDrag + ? draggedBlockClientIds.includes( clientId ) + : false, + innerBlockCount: getBlockCount( clientId ), + canInsertDraggedBlocksAsSibling: isBlockDrag + ? canInsertBlocks( + draggedBlockClientIds, + rootClientId + ) + : true, + canInsertDraggedBlocksAsChild: isBlockDrag + ? canInsertBlocks( draggedBlockClientIds, clientId ) + : true, + }; + } ); - const newTarget = getListViewDropTarget( blocksData, position ); + const newTarget = getListViewDropTarget( blocksData, position ); - if ( newTarget ) { - setTarget( newTarget ); - } - }, [] ), + if ( newTarget ) { + setTarget( newTarget ); + } + }, + [ draggedBlockClientIds ] + ), 200 ); From 1649c9c63b6397a36e130080b48bdd8b540e0169 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 9 Jul 2021 13:23:39 +0800 Subject: [PATCH 07/16] Fix positioning when dropping to nested blocks --- .../components/list-view/drop-indicator.js | 96 +++++++++++++------ 1 file changed, 65 insertions(+), 31 deletions(-) diff --git a/packages/block-editor/src/components/list-view/drop-indicator.js b/packages/block-editor/src/components/list-view/drop-indicator.js index 3773ed0389a85d..1013a2548c98e5 100644 --- a/packages/block-editor/src/components/list-view/drop-indicator.js +++ b/packages/block-editor/src/components/list-view/drop-indicator.js @@ -12,64 +12,98 @@ import { useListViewContext } from './context'; export default function ListViewDropIndicator( { listViewRef } ) { const { blockDropTarget } = useListViewContext(); - const { clientId, dropPosition } = blockDropTarget || {}; + const { clientId, rootClientId, dropPosition } = blockDropTarget || {}; - const blockElement = useMemo( () => { - if ( ! clientId || ! listViewRef.current ) { - return; + const [ rootBlockElement, blockElement ] = useMemo( () => { + if ( ! listViewRef.current ) { + return []; } - return listViewRef.current.ownerDocument.getElementById( - `list-view-block-${ clientId }` + const ownerDocument = listViewRef.current.ownerDocument; + + const _rootBlockElement = rootClientId + ? ownerDocument.getElementById( + `list-view-block-${ rootClientId }` + ) + : undefined; + + const _blockElement = clientId + ? ownerDocument.getElementById( `list-view-block-${ clientId }` ) + : undefined; + + return [ _rootBlockElement, _blockElement ]; + }, [ rootClientId, clientId ] ); + + // The root block element is used when dropPosition 'inside', which + // means dropping a block into an empty inner blocks list. In this + // case there's no sibling block to use for positioning, so the + // root block is used instead. + const targetElement = blockElement || rootBlockElement; + + const getDropIndicatorIndent = useCallback( () => { + if ( ! rootBlockElement ) { + return 0; + } + + // Calculate the indent using the block icon of the root block. + const targetElementRect = targetElement.getBoundingClientRect(); + const rootBlockIconElement = rootBlockElement.querySelector( + '.block-editor-block-icon' ); - }, [ clientId ] ); + const rootBlockIconRect = rootBlockIconElement.getBoundingClientRect(); + return rootBlockIconRect.right - targetElementRect.left; + }, [ rootBlockElement, targetElement ] ); const style = useMemo( () => { - if ( ! blockElement ) { + if ( ! targetElement ) { return {}; } + const indent = getDropIndicatorIndent(); + return { - width: blockElement.offsetWidth, + width: targetElement.offsetWidth - indent, }; - }, [ blockElement ] ); + }, [ getDropIndicatorIndent, targetElement ] ); const getAnchorRect = useCallback( () => { - if ( ! blockElement ) { + if ( ! targetElement ) { return {}; } - const ownerDocument = blockElement.ownerDocument; - const rect = blockElement.getBoundingClientRect(); + const ownerDocument = targetElement.ownerDocument; + const rect = targetElement.getBoundingClientRect(); + const indent = getDropIndicatorIndent(); - if ( dropPosition === 'top' ) { - return { - top: rect.top, - bottom: rect.top, - left: rect.left, - right: rect.right, - width: 0, - height: rect.height, - ownerDocument, - }; - } + // The most common 'dropPosition' is bottom, so optimize for that. + const anchorRect = { + left: rect.left + indent, + right: rect.right, + width: 0, + height: rect.height, + ownerDocument, + }; if ( dropPosition === 'bottom' || dropPosition === 'inside' ) { return { + ...anchorRect, top: rect.bottom, bottom: rect.bottom, - left: rect.left, - right: rect.right, - width: 0, - height: rect.height, - ownerDocument, + }; + } + + if ( dropPosition === 'top' ) { + return { + ...anchorRect, + top: rect.top, + bottom: rect.top, }; } return {}; - }, [ blockElement, dropPosition ] ); + }, [ targetElement, getDropIndicatorIndent, dropPosition ] ); - if ( ! clientId ) { + if ( ! clientId && ! rootClientId ) { return null; } From e8af5b5b6f40ef5dbaf337393c573f8883988b7d Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 9 Jul 2021 13:40:17 +0800 Subject: [PATCH 08/16] Avoid using context and improve some comments --- .../components/list-view/drop-indicator.js | 45 ++++++++++--------- .../src/components/list-view/index.js | 7 +-- 2 files changed, 27 insertions(+), 25 deletions(-) diff --git a/packages/block-editor/src/components/list-view/drop-indicator.js b/packages/block-editor/src/components/list-view/drop-indicator.js index 1013a2548c98e5..be03f502ded485 100644 --- a/packages/block-editor/src/components/list-view/drop-indicator.js +++ b/packages/block-editor/src/components/list-view/drop-indicator.js @@ -4,15 +4,11 @@ import { Popover } from '@wordpress/components'; import { useCallback, useMemo } from '@wordpress/element'; -/** - * Internal dependencies - */ -import { useListViewContext } from './context'; - -export default function ListViewDropIndicator( { listViewRef } ) { - const { blockDropTarget } = useListViewContext(); - - const { clientId, rootClientId, dropPosition } = blockDropTarget || {}; +export default function ListViewDropIndicator( { + listViewRef, + blockDropTarget, +} ) { + const { rootClientId, clientId, dropPosition } = blockDropTarget || {}; const [ rootBlockElement, blockElement ] = useMemo( () => { if ( ! listViewRef.current ) { @@ -21,12 +17,17 @@ export default function ListViewDropIndicator( { listViewRef } ) { const ownerDocument = listViewRef.current.ownerDocument; + // The rootClientId will be defined whenever dropping into inner + // block lists, but is undefined when dropping at the root level. const _rootBlockElement = rootClientId ? ownerDocument.getElementById( `list-view-block-${ rootClientId }` ) : undefined; + // The clientId represents the sibling block, the dragged block will + // usually be inserted adjacent to it. It will be undefined when + // dropping a block into an empty block list. const _blockElement = clientId ? ownerDocument.getElementById( `list-view-block-${ clientId }` ) : undefined; @@ -34,10 +35,9 @@ export default function ListViewDropIndicator( { listViewRef } ) { return [ _rootBlockElement, _blockElement ]; }, [ rootClientId, clientId ] ); - // The root block element is used when dropPosition 'inside', which - // means dropping a block into an empty inner blocks list. In this - // case there's no sibling block to use for positioning, so the - // root block is used instead. + // The targetElement is the element that the drop indicator will appear + // before or after. When dropping into an empty block list, blockElement + // is undefined, so the indicator will appear after the rootBlockElement. const targetElement = blockElement || rootBlockElement; const getDropIndicatorIndent = useCallback( () => { @@ -46,6 +46,8 @@ export default function ListViewDropIndicator( { listViewRef } ) { } // Calculate the indent using the block icon of the root block. + // Using a classname selector here might be flaky and could be + // improved. const targetElementRect = targetElement.getBoundingClientRect(); const rootBlockIconElement = rootBlockElement.querySelector( '.block-editor-block-icon' @@ -75,7 +77,6 @@ export default function ListViewDropIndicator( { listViewRef } ) { const rect = targetElement.getBoundingClientRect(); const indent = getDropIndicatorIndent(); - // The most common 'dropPosition' is bottom, so optimize for that. const anchorRect = { left: rect.left + indent, right: rect.right, @@ -84,26 +85,26 @@ export default function ListViewDropIndicator( { listViewRef } ) { ownerDocument, }; - if ( dropPosition === 'bottom' || dropPosition === 'inside' ) { + if ( dropPosition === 'top' ) { return { ...anchorRect, - top: rect.bottom, - bottom: rect.bottom, + top: rect.top, + bottom: rect.top, }; } - if ( dropPosition === 'top' ) { + if ( dropPosition === 'bottom' || dropPosition === 'inside' ) { return { ...anchorRect, - top: rect.top, - bottom: rect.top, + top: rect.bottom, + bottom: rect.bottom, }; } return {}; - }, [ targetElement, getDropIndicatorIndent, dropPosition ] ); + }, [ targetElement, dropPosition, getDropIndicatorIndent ] ); - if ( ! clientId && ! rootClientId ) { + if ( ! targetElement ) { return null; } diff --git a/packages/block-editor/src/components/list-view/index.js b/packages/block-editor/src/components/list-view/index.js index 3945351388966b..8374314e29849e 100644 --- a/packages/block-editor/src/components/list-view/index.js +++ b/packages/block-editor/src/components/list-view/index.js @@ -104,7 +104,6 @@ export default function ListView( { () => ( { __experimentalFeatures, __experimentalPersistentListViewFeatures, - blockDropTarget, isTreeGridMounted: isMounted.current, expandedState, expand, @@ -113,7 +112,6 @@ export default function ListView( { [ __experimentalFeatures, __experimentalPersistentListViewFeatures, - blockDropTarget, isMounted.current, expandedState, expand, @@ -123,7 +121,10 @@ export default function ListView( { return ( - + Date: Fri, 9 Jul 2021 14:48:10 +0800 Subject: [PATCH 09/16] Move provider back --- .../src/components/list-view/index.js | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/packages/block-editor/src/components/list-view/index.js b/packages/block-editor/src/components/list-view/index.js index 8374314e29849e..1fa3f75b64ced5 100644 --- a/packages/block-editor/src/components/list-view/index.js +++ b/packages/block-editor/src/components/list-view/index.js @@ -120,7 +120,7 @@ export default function ListView( { ); return ( - + <> - + + + - + ); } From 1d0fcbe3742470cdef7483eb88deff16c787cfca Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 9 Jul 2021 16:37:06 +0800 Subject: [PATCH 10/16] Update naming in block navigation test --- .../editor/various/block-hierarchy-navigation.test.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/e2e-tests/specs/editor/various/block-hierarchy-navigation.test.js b/packages/e2e-tests/specs/editor/various/block-hierarchy-navigation.test.js index fd057e84853381..766a5daceeb934 100644 --- a/packages/e2e-tests/specs/editor/various/block-hierarchy-navigation.test.js +++ b/packages/e2e-tests/specs/editor/various/block-hierarchy-navigation.test.js @@ -10,7 +10,7 @@ import { openDocumentSettingsSidebar, } from '@wordpress/e2e-test-utils'; -async function openBlockNavigator() { +async function openListViewSidebar() { await pressKeyWithModifier( 'access', 'o' ); await page.waitForSelector( '.block-editor-list-view-leaf.is-selected' ); } @@ -35,7 +35,7 @@ describe( 'Navigating the block hierarchy', () => { await createNewPost(); } ); - it( 'should navigate using the block hierarchy dropdown menu', async () => { + it( 'should navigate using the list view sidebar', async () => { await insertBlock( 'Columns' ); await page.click( '[aria-label="Two columns; equal split"]' ); @@ -105,7 +105,7 @@ describe( 'Navigating the block hierarchy', () => { await page.keyboard.type( 'First column' ); // Navigate to the columns blocks using the keyboard. - await openBlockNavigator(); + await openListViewSidebar(); await pressKeyTimes( 'ArrowUp', 2 ); await page.keyboard.press( 'Enter' ); @@ -150,7 +150,7 @@ describe( 'Navigating the block hierarchy', () => { await insertBlock( 'Image' ); // Return to first block. - await openBlockNavigator(); + await openListViewSidebar(); await page.keyboard.press( 'ArrowUp' ); await page.keyboard.press( 'Space' ); From 8da5546cc04233dcf317e5bf00a7d54ce6af57d9 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 9 Jul 2021 18:24:24 +0800 Subject: [PATCH 11/16] Add basic e2e tests --- .../__snapshots__/list-view.test.js.snap | 15 +++++ .../specs/editor/various/list-view.test.js | 64 +++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 packages/e2e-tests/specs/editor/various/__snapshots__/list-view.test.js.snap create mode 100644 packages/e2e-tests/specs/editor/various/list-view.test.js diff --git a/packages/e2e-tests/specs/editor/various/__snapshots__/list-view.test.js.snap b/packages/e2e-tests/specs/editor/various/__snapshots__/list-view.test.js.snap new file mode 100644 index 00000000000000..f0dcd9ca28ff42 --- /dev/null +++ b/packages/e2e-tests/specs/editor/various/__snapshots__/list-view.test.js.snap @@ -0,0 +1,15 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`List view allows a user to drag a block to a new sibling position 1`] = ` +" +

+ + + +

+ + + +
\\"\\"/
+" +`; diff --git a/packages/e2e-tests/specs/editor/various/list-view.test.js b/packages/e2e-tests/specs/editor/various/list-view.test.js new file mode 100644 index 00000000000000..dcb936733b4ec3 --- /dev/null +++ b/packages/e2e-tests/specs/editor/various/list-view.test.js @@ -0,0 +1,64 @@ +/** + * WordPress dependencies + */ +import { + createNewPost, + insertBlock, + getEditedPostContent, + pressKeyWithModifier, +} from '@wordpress/e2e-test-utils'; + +async function dragAndDrop( draggableElement, targetElement, offsetY ) { + const draggableRect = await draggableElement.boundingBox(); + const dragPosition = { + x: draggableRect.x + draggableRect.width / 2, + y: draggableRect.y + draggableRect.height / 2, + }; + + const targetRect = await targetElement.boundingBox(); + const targetPosition = { + x: targetRect.x + targetRect.width / 2, + y: offsetY + targetRect.y + targetRect.height / 2, + }; + + return await page.mouse.dragAndDrop( dragPosition, targetPosition, { + delay: 1000, + } ); +} + +describe( 'List view', () => { + beforeAll( async () => { + await page.setDragInterception( true ); + } ); + + beforeEach( async () => { + await createNewPost(); + } ); + + afterAll( async () => { + await page.setDragInterception( false ); + } ); + + it( 'allows a user to drag a block to a new sibling position', async () => { + // Insert some blocks of different types. + await insertBlock( 'Heading' ); + await insertBlock( 'Image' ); + await insertBlock( 'Paragraph' ); + + // Open list view. + await pressKeyWithModifier( 'access', 'o' ); + + const paragraphBlock = await page.waitForXPath( + '//button[contains(., "Paragraph")][@draggable="true"]' + ); + + // Drag above the heading block + const headingBlock = await page.waitForXPath( + '//button[contains(., "Heading")][@draggable="true"]' + ); + + await dragAndDrop( paragraphBlock, headingBlock, -5 ); + + expect( await getEditedPostContent() ).toMatchSnapshot(); + } ); +} ); From c4a970d21d3e61f5e59af08604d5d51231df92c6 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 9 Jul 2021 18:49:34 +0800 Subject: [PATCH 12/16] Update renamed test snapshot --- .../block-hierarchy-navigation.test.js.snap | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap b/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap index 406e1be99232c7..91298787a8ee84 100644 --- a/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap +++ b/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap @@ -50,6 +50,26 @@ exports[`Navigating the block hierarchy should navigate using the block hierarch " `; +exports[`Navigating the block hierarchy should navigate using the list view sidebar 1`] = ` +" +
+
+

First column

+
+ + + +
+ + + +
+

Third column

+
+
+" +`; + exports[`Navigating the block hierarchy should select the wrapper div for a group 1`] = ` "
From 92991881e48f89f1912d905d6908b6733c7ac151 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 9 Jul 2021 18:56:53 +0800 Subject: [PATCH 13/16] Simplify tests --- .../specs/editor/various/list-view.test.js | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/e2e-tests/specs/editor/various/list-view.test.js b/packages/e2e-tests/specs/editor/various/list-view.test.js index dcb936733b4ec3..a123d16feae6eb 100644 --- a/packages/e2e-tests/specs/editor/various/list-view.test.js +++ b/packages/e2e-tests/specs/editor/various/list-view.test.js @@ -9,19 +9,14 @@ import { } from '@wordpress/e2e-test-utils'; async function dragAndDrop( draggableElement, targetElement, offsetY ) { - const draggableRect = await draggableElement.boundingBox(); - const dragPosition = { - x: draggableRect.x + draggableRect.width / 2, - y: draggableRect.y + draggableRect.height / 2, + const draggablePoint = await draggableElement.clickablePoint(); + const targetClickablePoint = await targetElement.clickablePoint(); + const targetPoint = { + x: targetClickablePoint.x, + y: targetClickablePoint.y + offsetY, }; - const targetRect = await targetElement.boundingBox(); - const targetPosition = { - x: targetRect.x + targetRect.width / 2, - y: offsetY + targetRect.y + targetRect.height / 2, - }; - - return await page.mouse.dragAndDrop( dragPosition, targetPosition, { + return await page.mouse.dragAndDrop( draggablePoint, targetPoint, { delay: 1000, } ); } From 1c629aa1808bc8b505340b3100653704f1c14d83 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 9 Jul 2021 19:01:11 +0800 Subject: [PATCH 14/16] Remove delay --- packages/e2e-tests/specs/editor/various/list-view.test.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/e2e-tests/specs/editor/various/list-view.test.js b/packages/e2e-tests/specs/editor/various/list-view.test.js index a123d16feae6eb..24ffb70821075c 100644 --- a/packages/e2e-tests/specs/editor/various/list-view.test.js +++ b/packages/e2e-tests/specs/editor/various/list-view.test.js @@ -16,9 +16,7 @@ async function dragAndDrop( draggableElement, targetElement, offsetY ) { y: targetClickablePoint.y + offsetY, }; - return await page.mouse.dragAndDrop( draggablePoint, targetPoint, { - delay: 1000, - } ); + return await page.mouse.dragAndDrop( draggablePoint, targetPoint ); } describe( 'List view', () => { From a6bdb3fd3132f792f96e523e7ceb889047e6a011 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Fri, 9 Jul 2021 20:16:09 +0800 Subject: [PATCH 15/16] Remove obsolete snapshot --- .../block-hierarchy-navigation.test.js.snap | 20 ------------------- 1 file changed, 20 deletions(-) diff --git a/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap b/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap index 91298787a8ee84..75dd24a83136f7 100644 --- a/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap +++ b/packages/e2e-tests/specs/editor/various/__snapshots__/block-hierarchy-navigation.test.js.snap @@ -30,26 +30,6 @@ exports[`Navigating the block hierarchy should navigate block hierarchy using on " `; -exports[`Navigating the block hierarchy should navigate using the block hierarchy dropdown menu 1`] = ` -" -
-
-

First column

-
- - - -
- - - -
-

Third column

-
-
-" -`; - exports[`Navigating the block hierarchy should navigate using the list view sidebar 1`] = ` "
From d1ab2124524a28b3c93c9397433a9df7168ca036 Mon Sep 17 00:00:00 2001 From: Daniel Richards Date: Mon, 12 Jul 2021 15:50:17 +0800 Subject: [PATCH 16/16] Fix incorrect drop indicator showing when two list views are open. Remove duplicate ids --- .../src/components/block-draggable/index.js | 2 -- .../src/components/list-view/block-contents.js | 5 +---- .../src/components/list-view/drop-indicator.js | 10 +++++----- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/packages/block-editor/src/components/block-draggable/index.js b/packages/block-editor/src/components/block-draggable/index.js index 71da2b075c49ca..b1e539654f8537 100644 --- a/packages/block-editor/src/components/block-draggable/index.js +++ b/packages/block-editor/src/components/block-draggable/index.js @@ -19,7 +19,6 @@ const BlockDraggable = ( { cloneClassname, onDragStart, onDragEnd, - elementId, } ) => { const { srcRootClientId, isDraggable, icon } = useSelect( ( select ) => { @@ -75,7 +74,6 @@ const BlockDraggable = ( { return ( { diff --git a/packages/block-editor/src/components/list-view/block-contents.js b/packages/block-editor/src/components/list-view/block-contents.js index 18215ecfba6b4b..d3bfd824cfef25 100644 --- a/packages/block-editor/src/components/list-view/block-contents.js +++ b/packages/block-editor/src/components/list-view/block-contents.js @@ -60,10 +60,7 @@ const ListViewBlockContents = forwardRef( } ); return ( - + { ( { draggable, onDragStart, onDragEnd } ) => __experimentalFeatures ? (