Skip to content

Commit

Permalink
Include multi selection nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
ellatrix committed Jan 21, 2020
1 parent d332702 commit 77b3081
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 34 deletions.
23 changes: 18 additions & 5 deletions packages/block-editor/src/components/block-list/block-popover.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { useViewportMatch } from '@wordpress/compose';
import BlockBreadcrumb from './breadcrumb';
import BlockContextualToolbar from './block-contextual-toolbar';
import Inserter from '../inserter';
import { SelectedBlockNode } from './root-container';
import { BlockNodes } from './root-container';

function selector( select ) {
const {
Expand All @@ -30,6 +30,7 @@ function selector( select ) {
isTyping,
isCaretWithinFormattedText,
getSettings,
getLastMultiSelectedBlockClientId,
} = select( 'core/block-editor' );
return {
isNavigationMode: isNavigationMode(),
Expand All @@ -38,6 +39,7 @@ function selector( select ) {
isCaretWithinFormattedText: isCaretWithinFormattedText(),
hasMultiSelection: hasMultiSelection(),
hasFixedToolbar: getSettings().hasFixedToolbar,
lastClientId: getLastMultiSelectedBlockClientId(),
};
}

Expand All @@ -58,11 +60,12 @@ function BlockPopover( {
isCaretWithinFormattedText,
hasMultiSelection,
hasFixedToolbar,
lastClientId,
} = useSelect( selector, [] );
const isLargeViewport = useViewportMatch( 'medium' );
const [ isToolbarForced, setIsToolbarForced ] = useState( false );
const [ isInserterShown, setIsInserterShown ] = useState( false );
let [ node ] = useContext( SelectedBlockNode );
const [ blockNodes ] = useContext( BlockNodes );

const showEmptyBlockSideInserter = ! isNavigationMode && isEmptyDefaultBlock && isValid;
const shouldShowBreadcrumb = isNavigationMode;
Expand Down Expand Up @@ -94,6 +97,8 @@ function BlockPopover( {
return null;
}

let node = blockNodes[ clientId ];

if ( capturingClientId ) {
node = document.getElementById( 'block-' + capturingClientId );
}
Expand All @@ -107,6 +112,15 @@ function BlockPopover( {
node = node.querySelector( '.is-block-content' ) || node;
}

let anchorRef = node;

if ( hasMultiSelection ) {
anchorRef = {
top: blockNodes[ clientId ],
bottom: blockNodes[ lastClientId ],
};
}

function onFocus() {
setIsInserterShown( true );
}
Expand All @@ -120,17 +134,16 @@ function BlockPopover( {
// position in the right corner.
// To do: refactor `Popover` to make this prop clearer.
const popoverPosition = showEmptyBlockSideInserter ? 'top left right' : 'top right left';
const popoverIsSticky = hasMultiSelection ? '.wp-block.is-multi-selected' : true;

return (
<Popover
noArrow
animate={ false }
position={ popoverPosition }
focusOnMount={ false }
anchorRef={ node }
anchorRef={ anchorRef }
className="block-editor-block-list__block-popover"
__unstableSticky={ showEmptyBlockSideInserter ? false : popoverIsSticky }
__unstableSticky={ ! showEmptyBlockSideInserter }
__unstableSlotName="block-toolbar"
// Allow subpixel positioning for the block movement animation.
__unstableAllowVerticalSubpixelPosition={ moverDirection !== 'horizontal' && node }
Expand Down
17 changes: 10 additions & 7 deletions packages/block-editor/src/components/block-list/block.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* External dependencies
*/
import classnames from 'classnames';
import { first, last } from 'lodash';
import { first, last, omit } from 'lodash';
import { animated } from 'react-spring/web.cjs';

/**
Expand Down Expand Up @@ -42,7 +42,7 @@ import BlockCrashBoundary from './block-crash-boundary';
import BlockHtml from './block-html';
import { isInsideRootBlock } from '../../utils/dom';
import useMovingAnimation from './moving-animation';
import { Context, SelectedBlockNode } from './root-container';
import { Context, BlockNodes } from './root-container';

function BlockListBlock( {
mode,
Expand All @@ -53,6 +53,7 @@ function BlockListBlock( {
isMultiSelected,
isPartOfMultiSelection,
isFirstMultiSelected,
isLastMultiSelected,
isTypingWithinBlock,
isEmptyDefaultBlock,
isAncestorOfSelectedBlock,
Expand All @@ -77,7 +78,7 @@ function BlockListBlock( {
hasSelectedUI = true,
} ) {
const onSelectionStart = useContext( Context );
const [ , setSelectedBlockNode ] = useContext( SelectedBlockNode );
const [ , setBlockNodes ] = useContext( BlockNodes );
// In addition to withSelect, we should favor using useSelect in this component going forward
// to avoid leaking new props to the public API (editor.BlockListBlock filter)
const { isDraggingBlocks } = useSelect( ( select ) => {
Expand All @@ -90,14 +91,14 @@ function BlockListBlock( {
const wrapper = useRef( null );

useLayoutEffect( () => {
if ( isSelected || isFirstMultiSelected ) {
if ( isSelected || isFirstMultiSelected || isLastMultiSelected ) {
const node = wrapper.current;
setSelectedBlockNode( node );
setBlockNodes( ( nodes ) => ( { ...nodes, [ clientId ]: node } ) );
return () => {
setSelectedBlockNode( ( n ) => n === node ? null : n );
setBlockNodes( ( nodes ) => omit( nodes, clientId ) );
};
}
}, [ isSelected, isFirstMultiSelected ] );
}, [ isSelected, isFirstMultiSelected, isLastMultiSelected ] );

// Handling the error state
const [ hasError, setErrorState ] = useState( false );
Expand Down Expand Up @@ -332,6 +333,7 @@ const applyWithSelect = withSelect(
isAncestorMultiSelected,
isBlockMultiSelected,
isFirstMultiSelectedBlock,
getLastMultiSelectedBlockClientId,
isTyping,
getBlockMode,
isSelectionEnabled,
Expand Down Expand Up @@ -362,6 +364,7 @@ const applyWithSelect = withSelect(
isPartOfMultiSelection:
isBlockMultiSelected( clientId ) || isAncestorMultiSelected( clientId ),
isFirstMultiSelected: isFirstMultiSelectedBlock( clientId ),
isLastMultiSelected: getLastMultiSelectedBlockClientId() === clientId,

// We only care about this prop when the block is selected
// Thus to avoid unnecessary rerenders we avoid updating the prop if the block is not selected.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import BlockPopover from './block-popover';
/** @typedef {import('@wordpress/element').WPSyntheticEvent} WPSyntheticEvent */

export const Context = createContext();
export const SelectedBlockNode = createContext();
export const BlockNodes = createContext();

function selector( select ) {
const {
Expand Down Expand Up @@ -81,7 +81,7 @@ function RootContainer( { children, className }, ref ) {
selectedBlockClientId={ selectedBlockClientId }
containerRef={ ref }
>
<SelectedBlockNode.Provider value={ useState( null ) }>
<BlockNodes.Provider value={ useState( {} ) }>
<BlockPopover />
<div
ref={ ref }
Expand All @@ -93,7 +93,7 @@ function RootContainer( { children, className }, ref ) {
{ children }
</Context.Provider>
</div>
</SelectedBlockNode.Provider>
</BlockNodes.Provider>
</InsertionPoint>
);
}
Expand Down
22 changes: 20 additions & 2 deletions packages/components/src/popover/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,25 @@ function computeAnchorRect(
return getRectangleFromRange( anchorRef );
}

const rect = anchorRef.getBoundingClientRect();
if ( anchorRef instanceof window.Element ) {
const rect = anchorRef.getBoundingClientRect();

if ( shouldAnchorIncludePadding ) {
return rect;
}

return withoutPadding( rect, anchorRef );
}

const { top, bottom } = anchorRef;
const topRect = top.getBoundingClientRect();
const bottomRect = bottom.getBoundingClientRect();
const rect = new window.DOMRect(
topRect.left,
topRect.top,
topRect.width,
bottomRect.bottom - topRect.top
);

if ( shouldAnchorIncludePadding ) {
return rect;
Expand Down Expand Up @@ -280,7 +298,7 @@ const Popover = ( {
yAxis,
contentHeight,
contentWidth,
} = computePopoverPosition( anchor, contentRect.current, position, __unstableSticky, anchorRef );
} = computePopoverPosition( anchor, contentRect.current, position, __unstableSticky, containerRef.current );

if ( typeof popoverTop === 'number' && typeof popoverLeft === 'number' ) {
if ( subpixels && __unstableAllowVerticalSubpixelPosition ) {
Expand Down
20 changes: 3 additions & 17 deletions packages/components/src/popover/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,27 +126,13 @@ export function computePopoverYAxisPosition( anchorRect, contentSize, yAxis, cor
const { height } = contentSize;

if ( sticky ) {
let topEl = anchorRef;
let bottomEl = anchorRef;

if ( typeof sticky === 'string' ) {
const elements = document.querySelectorAll( sticky );

if ( elements.length ) {
topEl = elements[ 0 ];
bottomEl = elements[ elements.length - 1 ];
}
}

const scrollContainerEl = getScrollContainer( topEl ) || document.body;
const scrollContainerEl = getScrollContainer( anchorRef ) || document.body;
const scrollRect = scrollContainerEl.getBoundingClientRect();
const topRect = topEl.getBoundingClientRect();
const bottomRect = bottomEl.getBoundingClientRect();

if ( topRect.top - height <= scrollRect.top ) {
if ( anchorRect.top - height <= scrollRect.top ) {
return {
yAxis,
popoverTop: Math.min( bottomRect.bottom, scrollRect.top + height ),
popoverTop: Math.min( anchorRect.bottom, scrollRect.top + height ),
};
}
}
Expand Down

0 comments on commit 77b3081

Please sign in to comment.