Skip to content

Commit

Permalink
Zoom out: Try vertical displacement when dragging a pattern between e…
Browse files Browse the repository at this point in the history
…xisting patterns/sections (#63896)

* create a function to check when we can add the separators

Attempt to define sectionClientIds

Pass sectionClientIds to isSectionBlock

Rename sectionClientIds to sectionRootClientIds

check if it's zoom out mode, add some CSS to the separator

expand separators when the insertion point is changed

fix animation

only open the first separator if the insertion point index is 0

conditionally render the separators and animate them using framer instead of on class change

remove unused code

refactor separators

do displacement on drag

* Don’t show seperator if opertation is not insert

* Fix bug where rootClientId was not within sectionRoot

* Ignore Group operations on drag in Zoom Out mode

* Check for ZoomOut separators when firing onDragEnd

* Refine function to detect zoom out separator

* Update detection based on data attribute

* Make generic

* Add comment for clarity

* Improve code comments

* Remove blue line inserter in ZoomOutmode

* Move logic into consuming hook

* Consume new API for getting root

* Move pure function

* Fix background showing through

* Add UI feedback on dragover separator

---------

Co-authored-by: Dave Smith <[email protected]>
Co-authored-by: MaggieCabrera <[email protected]>
Co-authored-by: getdave <[email protected]>
Co-authored-by: Mamaduka <[email protected]>
Co-authored-by: scruffian <[email protected]>
Co-authored-by: andrewserong <[email protected]>
Co-authored-by: richtabor <[email protected]>
  • Loading branch information
8 people authored Sep 6, 2024
1 parent e706d67 commit 95c1995
Show file tree
Hide file tree
Showing 7 changed files with 226 additions and 52 deletions.
21 changes: 21 additions & 0 deletions packages/block-editor/src/components/block-list/content.scss
Original file line number Diff line number Diff line change
Expand Up @@ -453,3 +453,24 @@ _::-webkit-full-page-media, _:future, :root .has-multi-selection .block-editor-b
margin-bottom: auto;
}
}

.block-editor-block-list__zoom-out-separator {
/* same color as the iframe's background */
background: $gray-300;
// Additional -1px is required to avoid sub pixel rounding errors allowing background to show.
margin-left: -1px;
margin-right: -1px;
transition: background-color 0.3s ease;

&.is-dragged-over {
background: $gray-400;
}
}

// In Post Editor allow the separator to occupy the full width by ignoring (cancelling out) the global padding.
.has-global-padding > .block-editor-block-list__zoom-out-separator,
.block-editor-block-list__layout.is-root-container.has-global-padding > .block-editor-block-list__zoom-out-separator {
max-width: none;
// Additional -1px is required to avoid sub pixel rounding errors allowing background to show.
margin: 0 calc(-1 * var(--wp--style--root--padding-right) - 1px) 0 calc(-1 * var(--wp--style--root--padding-left) - 1px) !important;
}
97 changes: 59 additions & 38 deletions packages/block-editor/src/components/block-list/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import {
DEFAULT_BLOCK_EDIT_CONTEXT,
} from '../block-edit/context';
import { useTypingObserver } from '../observe-typing';
import { ZoomOutSeparator } from './zoom-out-separator';
import { unlock } from '../../lock-unlock';

export const IntersectionObserver = createContext();
Expand Down Expand Up @@ -174,49 +175,55 @@ function Items( {
// function on every render.
const hasAppender = CustomAppender !== false;
const hasCustomAppender = !! CustomAppender;
const { order, selectedBlocks, visibleBlocks, shouldRenderAppender } =
useSelect(
( select ) => {
const {
getSettings,
getBlockOrder,
getSelectedBlockClientId,
getSelectedBlockClientIds,
__unstableGetVisibleBlocks,
getTemplateLock,
getBlockEditingMode,
__unstableGetEditorMode,
} = select( blockEditorStore );

const _order = getBlockOrder( rootClientId );
const {
order,
isZoomOut,
selectedBlocks,
visibleBlocks,
shouldRenderAppender,
} = useSelect(
( select ) => {
const {
getSettings,
getBlockOrder,
getSelectedBlockClientId,
getSelectedBlockClientIds,
__unstableGetVisibleBlocks,
getTemplateLock,
getBlockEditingMode,
__unstableGetEditorMode,
} = select( blockEditorStore );

if ( getSettings().__unstableIsPreviewMode ) {
return {
order: _order,
selectedBlocks: EMPTY_ARRAY,
visibleBlocks: EMPTY_SET,
};
}
const _order = getBlockOrder( rootClientId );

const selectedBlockClientId = getSelectedBlockClientId();
if ( getSettings().__unstableIsPreviewMode ) {
return {
order: _order,
selectedBlocks: getSelectedBlockClientIds(),
visibleBlocks: __unstableGetVisibleBlocks(),
shouldRenderAppender:
hasAppender &&
__unstableGetEditorMode() !== 'zoom-out' &&
( hasCustomAppender
? ! getTemplateLock( rootClientId ) &&
getBlockEditingMode( rootClientId ) !== 'disabled'
: rootClientId === selectedBlockClientId ||
( ! rootClientId &&
! selectedBlockClientId &&
! _order.length ) ),
selectedBlocks: EMPTY_ARRAY,
visibleBlocks: EMPTY_SET,
};
},
[ rootClientId, hasAppender, hasCustomAppender ]
);
}

const selectedBlockClientId = getSelectedBlockClientId();
return {
order: _order,
selectedBlocks: getSelectedBlockClientIds(),
visibleBlocks: __unstableGetVisibleBlocks(),
isZoomOut: __unstableGetEditorMode() === 'zoom-out',
shouldRenderAppender:
hasAppender &&
__unstableGetEditorMode() !== 'zoom-out' &&
( hasCustomAppender
? ! getTemplateLock( rootClientId ) &&
getBlockEditingMode( rootClientId ) !== 'disabled'
: rootClientId === selectedBlockClientId ||
( ! rootClientId &&
! selectedBlockClientId &&
! _order.length ) ),
};
},
[ rootClientId, hasAppender, hasCustomAppender ]
);

return (
<LayoutProvider value={ layout }>
Expand All @@ -230,10 +237,24 @@ function Items( {
! selectedBlocks.includes( clientId )
}
>
{ isZoomOut && (
<ZoomOutSeparator
clientId={ clientId }
rootClientId={ rootClientId }
position="top"
/>
) }
<BlockListBlock
rootClientId={ rootClientId }
clientId={ clientId }
/>
{ isZoomOut && (
<ZoomOutSeparator
clientId={ clientId }
rootClientId={ rootClientId }
position="bottom"
/>
) }
</AsyncModeProvider>
) ) }
{ order.length < 1 && placeholder }
Expand Down
110 changes: 110 additions & 0 deletions packages/block-editor/src/components/block-list/zoom-out-separator.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/**
* External dependencies
*/
import clsx from 'clsx';

/**
* WordPress dependencies
*/
import {
__unstableMotion as motion,
__unstableAnimatePresence as AnimatePresence,
} from '@wordpress/components';
import { useReducedMotion } from '@wordpress/compose';
import { useSelect } from '@wordpress/data';
import { useState } from '@wordpress/element';

/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';
import { unlock } from '../../lock-unlock';

export function ZoomOutSeparator( {
clientId,
rootClientId = '',
position = 'top',
} ) {
const [ isDraggedOver, setIsDraggedOver ] = useState( false );
const {
sectionRootClientId,
sectionClientIds,
blockInsertionPoint,
blockInsertionPointVisible,
} = useSelect( ( select ) => {
const {
getBlockInsertionPoint,
getBlockOrder,
isBlockInsertionPointVisible,
getSectionRootClientId,
} = unlock( select( blockEditorStore ) );

const root = getSectionRootClientId();
const sectionRootClientIds = getBlockOrder( root );
return {
sectionRootClientId: root,
sectionClientIds: sectionRootClientIds,
blockOrder: getBlockOrder( root ),
blockInsertionPoint: getBlockInsertionPoint(),
blockInsertionPointVisible: isBlockInsertionPointVisible(),
};
}, [] );

const isReducedMotion = useReducedMotion();

if ( ! clientId ) {
return;
}

let isVisible = false;

const isSectionBlock =
rootClientId === sectionRootClientId &&
sectionClientIds &&
sectionClientIds.includes( clientId );

if ( ! isSectionBlock ) {
return null;
}

if ( position === 'top' ) {
isVisible =
blockInsertionPointVisible &&
blockInsertionPoint.index === 0 &&
clientId === sectionClientIds[ blockInsertionPoint.index ];
}

if ( position === 'bottom' ) {
isVisible =
blockInsertionPointVisible &&
clientId === sectionClientIds[ blockInsertionPoint.index - 1 ];
}

return (
<AnimatePresence>
{ isVisible && (
<motion.div
as="button"
layout={ ! isReducedMotion }
initial={ { height: 0 } }
animate={ { height: '120px' } }
exit={ { height: 0 } }
transition={ {
type: 'tween',
duration: 0.2,
ease: [ 0.6, 0, 0.4, 1 ],
} }
className={ clsx(
'block-editor-block-list__zoom-out-separator',
{
'is-dragged-over': isDraggedOver,
}
) }
data-is-insertion-point="true"
onDragOver={ () => setIsDraggedOver( true ) }
onDragLeave={ () => setIsDraggedOver( false ) }
></motion.div>
) }
</AnimatePresence>
);
}
2 changes: 1 addition & 1 deletion packages/block-editor/src/components/block-tools/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ export default function BlockTools( {
// eslint-disable-next-line jsx-a11y/no-static-element-interactions
<div { ...props } onKeyDown={ onKeyDown }>
<InsertionPointOpenRef.Provider value={ useRef( false ) }>
{ ! isTyping && (
{ ! isTyping && ! isZoomOutMode && (
<InsertionPoint
__unstableContentRef={ __unstableContentRef }
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,18 +88,6 @@ function ZoomOutModeInserters() {
previousClientId={ previousClientId }
nextClientId={ nextClientId }
>
{ shouldRenderInsertionPoint && (
<div
style={ {
borderRadius: '0',
height: '12px',
opacity: 1,
transform: 'translateY(-50%)',
width: '100%',
} }
className="block-editor-block-list__insertion-point-indicator"
/>
) }
{ ! shouldRenderInsertionPoint && (
<ZoomOutModeInserterButton
isVisible={ isSelected || isHovered }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,23 @@ export function isDropTargetValid(
return areBlocksAllowed && targetMatchesDraggedBlockParents;
}

/**
* Checks if the given element is an insertion point.
*
* @param {EventTarget|null} targetToCheck - The element to check.
* @param {Document} ownerDocument - The owner document of the element.
* @return {boolean} True if the element is a insertion point, false otherwise.
*/
function isInsertionPoint( targetToCheck, ownerDocument ) {
const { defaultView } = ownerDocument;

return !! (
defaultView &&
targetToCheck instanceof defaultView.HTMLElement &&
targetToCheck.dataset.isInsertionPoint
);
}

/**
* @typedef {Object} WPBlockDropZoneConfig
* @property {?HTMLElement} dropZoneElement Optional element to be used as the drop zone.
Expand Down Expand Up @@ -422,6 +439,10 @@ export default function useBlockDropZone( {
const [ targetIndex, operation, nearestSide ] =
dropTargetPosition;

if ( isZoomOutMode() && operation !== 'insert' ) {
return;
}

if ( operation === 'group' ) {
const targetBlock = blocks[ targetIndex ];
const areAllImages = [
Expand Down Expand Up @@ -521,7 +542,18 @@ export default function useBlockDropZone( {
// https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget
throttled( event, event.currentTarget.ownerDocument );
},
onDragLeave() {
onDragLeave( event ) {
const { ownerDocument } = event.currentTarget;

// If the drag event is leaving the drop zone and entering an insertion point,
// do not hide the insertion point as it is conceptually within the dropzone.
if (
isInsertionPoint( event.relatedTarget, ownerDocument ) ||
isInsertionPoint( event.target, ownerDocument )
) {
return;
}

throttled.cancel();
hideInsertionPoint();
},
Expand Down
2 changes: 2 additions & 0 deletions packages/compose/src/hooks/use-drop-zone/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ export default function useDropZone( {
*/
function isElementInZone( targetToCheck ) {
const { defaultView } = ownerDocument;

if (
! targetToCheck ||
! defaultView ||
Expand Down Expand Up @@ -165,6 +166,7 @@ export default function useDropZone( {
// zone.
// Note: This is not entirely reliable in Safari due to this bug
// https://bugs.webkit.org/show_bug.cgi?id=66547

if ( isElementInZone( event.relatedTarget ) ) {
return;
}
Expand Down

0 comments on commit 95c1995

Please sign in to comment.