Skip to content

Commit

Permalink
Fix widget insertion from sidebar block library by using a declared i…
Browse files Browse the repository at this point in the history
…nsertionPoint prop (#25763)

* Fix widget insertion from sidebar block library by using a declared insertionPoint prop

* Add comments

* Optimize by avoiding `getEntityRecord` call unless needed
  • Loading branch information
talldan authored Oct 5, 2020
1 parent 97b4037 commit ff74b47
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ function useInsertionPoint( {
clientId,
isAppender,
selectBlockOnInsert,
insertionIndex,
} ) {
const {
destinationRootClientId,
Expand Down Expand Up @@ -76,14 +77,18 @@ function useInsertionPoint( {
} = useDispatch( 'core/block-editor' );

function getInsertionIndex() {
if ( insertionIndex !== undefined ) {
return insertionIndex;
}

// If the clientId is defined, we insert at the position of the block.
if ( clientId ) {
return getBlockIndex( clientId, destinationRootClientId );
}

// If there's a selected block, and the selected block is not the destination root block, we insert after the selected block.
const end = getBlockSelectionEnd();
if ( ! isAppender && end && end !== destinationRootClientId ) {
if ( ! isAppender && end ) {
return getBlockIndex( end, destinationRootClientId ) + 1;
}

Expand Down
8 changes: 6 additions & 2 deletions packages/block-editor/src/components/inserter/library.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ function InserterLibrary( {
isAppender,
showInserterHelpPanel,
showMostUsedBlocks = false,
__experimentalSelectBlockOnInsert: selectBlockOnInsert,
__experimentalSelectBlockOnInsert,
__experimentalInsertionIndex,
onSelect = noop,
} ) {
const destinationRootClientId = useSelect(
Expand All @@ -41,7 +42,10 @@ function InserterLibrary( {
isAppender={ isAppender }
showInserterHelpPanel={ showInserterHelpPanel }
showMostUsedBlocks={ showMostUsedBlocks }
__experimentalSelectBlockOnInsert={ selectBlockOnInsert }
__experimentalSelectBlockOnInsert={
__experimentalSelectBlockOnInsert
}
__experimentalInsertionIndex={ __experimentalInsertionIndex }
/>
);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/block-editor/src/components/inserter/menu.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ function InserterMenu( {
clientId,
isAppender,
__experimentalSelectBlockOnInsert,
__experimentalInsertionIndex,
onSelect,
showInserterHelpPanel,
showMostUsedBlocks,
Expand All @@ -46,6 +47,7 @@ function InserterMenu( {
clientId,
isAppender,
selectBlockOnInsert: __experimentalSelectBlockOnInsert,
insertionIndex: __experimentalInsertionIndex,
} );
const { hasPatterns, hasReusableBlocks } = useSelect( ( select ) => {
const {
Expand Down
14 changes: 8 additions & 6 deletions packages/edit-widgets/src/components/header/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,18 @@ import { useRef } from '@wordpress/element';
import SaveButton from '../save-button';
import UndoButton from './undo-redo/undo';
import RedoButton from './undo-redo/redo';
import useLastSelectedRootId from '../../hooks/use-last-selected-root-id';
import useLastSelectedWidgetArea from '../../hooks/use-last-selected-widget-area';

function Header() {
const inserterButton = useRef();
const isLargeViewport = useViewportMatch( 'medium' );
const rootClientId = useLastSelectedRootId();
const widgetAreaClientId = useLastSelectedWidgetArea();
const isLastSelectedWidgetAreaOpen = useSelect(
( select ) =>
select( 'core/edit-widgets' ).getIsWidgetAreaOpen( rootClientId ),
[ rootClientId ]
select( 'core/edit-widgets' ).getIsWidgetAreaOpen(
widgetAreaClientId
),
[ widgetAreaClientId ]
);
const isInserterOpened = useSelect( ( select ) =>
select( 'core/edit-widgets' ).isInserterOpened()
Expand All @@ -45,9 +47,9 @@ function Header() {
} else {
if ( ! isLastSelectedWidgetAreaOpen ) {
// Select the last selected block if hasn't already.
selectBlock( rootClientId );
selectBlock( widgetAreaClientId );
// Open the last selected widget area when opening the inserter.
setIsWidgetAreaOpen( rootClientId, true );
setIsWidgetAreaOpen( widgetAreaClientId, true );
}
// The DOM updates resulting from selectBlock() and setIsInserterOpened() calls are applied the
// same tick and pretty much in a random order. The inserter is closed if any other part of the
Expand Down
7 changes: 5 additions & 2 deletions packages/edit-widgets/src/components/layout/interface.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@ import { InterfaceSkeleton, ComplementaryArea } from '@wordpress/interface';
import Header from '../header';
import WidgetAreasBlockEditorContent from '../widget-areas-block-editor-content';
import PopoverWrapper from './popover-wrapper';
import useLastSelectedRootId from '../../hooks/use-last-selected-root-id';
import useWidgetLibraryInsertionPoint from '../../hooks/use-widget-library-insertion-point';

function Interface( { blockEditorSettings } ) {
const isMobileViewport = useViewportMatch( 'medium', '<' );
const isHugeViewport = useViewportMatch( 'huge', '>=' );
const { setIsInserterOpened, closeGeneralSidebar } = useDispatch(
'core/edit-widgets'
);
const rootClientId = useLastSelectedRootId( 'layout' );
const { rootClientId, insertionIndex } = useWidgetLibraryInsertionPoint();

const { hasSidebarEnabled, isInserterOpened } = useSelect( ( select ) => ( {
hasSidebarEnabled: !! select(
Expand Down Expand Up @@ -72,6 +72,9 @@ function Interface( { blockEditorSettings } ) {
}
} }
rootClientId={ rootClientId }
__experimentalInsertionIndex={
insertionIndex
}
/>
</div>
</div>
Expand Down
37 changes: 0 additions & 37 deletions packages/edit-widgets/src/hooks/use-last-selected-root-id.js

This file was deleted.

53 changes: 53 additions & 0 deletions packages/edit-widgets/src/hooks/use-last-selected-widget-area.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { buildWidgetAreasPostId, KIND, POST_TYPE } from '../store/utils';

/**
* A react hook that returns the client id of the last widget area to have
* been selected, or to have a selected block within it.
*
* @return {string} clientId of the widget area last selected.
*/
const useLastSelectedWidgetArea = () =>
useSelect( ( select ) => {
const { getBlockSelectionEnd, getBlockParents, getBlockName } = select(
'core/block-editor'
);
const blockSelectionEndClientId = getBlockSelectionEnd();

// If the selected block is a widget area, return its clientId.
if (
getBlockName( blockSelectionEndClientId ) === 'core/widget-area'
) {
return blockSelectionEndClientId;
}

// Otherwise, find the clientId of the top-level widget area by looking
// through the selected block's parents.
const blockParents = getBlockParents( blockSelectionEndClientId );
const rootWidgetAreaClientId = blockParents.find(
( clientId ) => getBlockName( clientId ) === 'core/widget-area'
);

if ( rootWidgetAreaClientId ) {
return rootWidgetAreaClientId;
}

// If no widget area has been selected, return the clientId of the first
// area.
const { getEntityRecord } = select( 'core' );
const widgetAreasPost = getEntityRecord(
KIND,
POST_TYPE,
buildWidgetAreasPostId()
);
return widgetAreasPost?.blocks[ 0 ]?.clientId;
}, [] );

export default useLastSelectedWidgetArea;
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { buildWidgetAreasPostId, KIND, POST_TYPE } from '../store/utils';

const useWidgetLibraryInsertionPoint = () => {
const firstRootId = useSelect( ( select ) => {
// Default to the first widget area
const { getEntityRecord } = select( 'core' );
const widgetAreasPost = getEntityRecord(
KIND,
POST_TYPE,
buildWidgetAreasPostId()
);
return widgetAreasPost?.blocks[ 0 ]?.clientId;
}, [] );

return useSelect(
( select ) => {
const {
getBlockRootClientId,
getBlockSelectionEnd,
getBlockOrder,
getBlockIndex,
} = select( 'core/block-editor' );

const clientId = getBlockSelectionEnd() || firstRootId;
const rootClientId = getBlockRootClientId( clientId );

// If the selected block is at the root level, it's a widget area and
// blocks can't be inserted here. Return this block as the root and the
// last child clientId indicating insertion at the end.
if ( clientId && rootClientId === '' ) {
return {
rootClientId: clientId,
insertionIndex: getBlockOrder( clientId ).length,
};
}

return {
rootClientId,
insertionIndex: getBlockIndex( clientId, rootClientId ) + 1,
};
},
[ firstRootId ]
);
};

export default useWidgetLibraryInsertionPoint;

0 comments on commit ff74b47

Please sign in to comment.