diff --git a/docs/reference-guides/data/data-core-block-editor.md b/docs/reference-guides/data/data-core-block-editor.md
index bf14e516719958..97011bcce91059 100644
--- a/docs/reference-guides/data/data-core-block-editor.md
+++ b/docs/reference-guides/data/data-core-block-editor.md
@@ -160,22 +160,16 @@ _Returns_
# **getBlockInsertionPoint**
-Returns the insertion point. This will be:
-
-1. The insertion point manually set using setInsertionPoint() or
- showInsertionPoint(); or
-2. The point after the current block selection, if there is a selection; or
-3. The point at the end of the block list.
-
-Components like will default to inserting blocks at this point.
+Returns the insertion point, the index at which the new inserted block would
+be placed. Defaults to the last index.
_Parameters_
-- _state_ `Object`: Global application state.
+- _state_ `Object`: Editor state.
_Returns_
-- `Object`: Insertion point object with `rootClientId` and `index`.
+- `Object`: Insertion point object with `rootClientId`, `index`.
# **getBlockListSettings**
@@ -853,8 +847,7 @@ _Returns_
# **isBlockInsertionPointVisible**
-Whether or not the insertion point should be shown to users. This is set
-using showInsertionPoint() or hideInsertionPoint().
+Returns true if we should show the block insertion point.
_Parameters_
@@ -862,7 +855,7 @@ _Parameters_
_Returns_
-- `?boolean`: Whether the insertion point should be shown.
+- `?boolean`: Whether the insertion point is visible or not.
# **isBlockMultiSelected**
@@ -1090,7 +1083,7 @@ _Parameters_
# **hideInsertionPoint**
-Hides the insertion point for users.
+Returns an action object hiding the insertion point.
_Returns_
@@ -1406,14 +1399,13 @@ _Returns_
# **showInsertionPoint**
-Sets the insertion point and shows it to users.
-
-Components like will default to inserting blocks at this point.
+Returns an action object used in signalling that the insertion point should
+be shown.
_Parameters_
-- _rootClientId_ `?string`: Root client ID of block list in which to insert. Use `undefined` for the root block list.
-- _index_ `number`: Index at which block should be inserted.
+- _rootClientId_ `?string`: Optional root client ID of block list on which to insert.
+- _index_ `?number`: Index at which block should be inserted.
_Returns_
diff --git a/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js b/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js
index 02ef1c0571107b..fec66c1ef0913d 100644
--- a/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js
+++ b/packages/block-editor/src/components/inserter/hooks/use-insertion-point.js
@@ -38,7 +38,7 @@ import { store as blockEditorStore } from '../../../store';
* @return {Array} Insertion Point State (rootClientID, onInsertBlocks and onToggle).
*/
function useInsertionPoint( {
- rootClientId,
+ rootClientId = '',
insertionIndex,
clientId,
isAppender,
@@ -49,40 +49,38 @@ function useInsertionPoint( {
const { destinationRootClientId, destinationIndex } = useSelect(
( select ) => {
const {
+ getSelectedBlockClientId,
+ getBlockRootClientId,
getBlockIndex,
getBlockOrder,
- getBlockInsertionPoint,
} = select( blockEditorStore );
-
- let _destinationRootClientId, _destinationIndex;
-
- if ( rootClientId || insertionIndex || clientId || isAppender ) {
- // If any of these arguments are set, we're in "manual mode"
- // meaning the insertion point is set by the caller.
-
- _destinationRootClientId = rootClientId;
-
- if ( insertionIndex ) {
- // Insert into a specific index.
- _destinationIndex = insertionIndex;
- } else if ( clientId ) {
- // Insert after a specific client ID.
- _destinationIndex = getBlockIndex(
- clientId,
- _destinationRootClientId
- );
- } else {
- // Insert at the end of the list.
- _destinationIndex = getBlockOrder(
+ const selectedBlockClientId = getSelectedBlockClientId();
+
+ let _destinationRootClientId = rootClientId;
+ let _destinationIndex;
+
+ if ( insertionIndex ) {
+ // Insert into a specific index.
+ _destinationIndex = insertionIndex;
+ } else if ( clientId ) {
+ // Insert after a specific client ID.
+ _destinationIndex = getBlockIndex(
+ clientId,
+ _destinationRootClientId
+ );
+ } else if ( ! isAppender && selectedBlockClientId ) {
+ _destinationRootClientId = getBlockRootClientId(
+ selectedBlockClientId
+ );
+ _destinationIndex =
+ getBlockIndex(
+ selectedBlockClientId,
_destinationRootClientId
- ).length;
- }
+ ) + 1;
} else {
- // Otherwise, we're in "auto mode" where the insertion point is
- // decided by getBlockInsertionPoint().
- const insertionPoint = getBlockInsertionPoint();
- _destinationRootClientId = insertionPoint.rootClientId;
- _destinationIndex = insertionPoint.index;
+ // Insert at the end of the list.
+ _destinationIndex = getBlockOrder( _destinationRootClientId )
+ .length;
}
return {
diff --git a/packages/block-editor/src/components/inserter/menu.js b/packages/block-editor/src/components/inserter/menu.js
index d18973d1d37dbb..13dda883f5b94a 100644
--- a/packages/block-editor/src/components/inserter/menu.js
+++ b/packages/block-editor/src/components/inserter/menu.js
@@ -190,6 +190,9 @@ function InserterMenu( {
rootClientId={ rootClientId }
clientId={ clientId }
isAppender={ isAppender }
+ __experimentalInsertionIndex={
+ __experimentalInsertionIndex
+ }
showBlockDirectory
shouldFocusBlock={ shouldFocusBlock }
/>
diff --git a/packages/block-editor/src/components/inserter/quick-inserter.js b/packages/block-editor/src/components/inserter/quick-inserter.js
index d880b2b4480673..ca4ff4c2fa2743 100644
--- a/packages/block-editor/src/components/inserter/quick-inserter.js
+++ b/packages/block-editor/src/components/inserter/quick-inserter.js
@@ -9,7 +9,7 @@ import classnames from 'classnames';
import { useState, useEffect } from '@wordpress/element';
import { __ } from '@wordpress/i18n';
import { Button } from '@wordpress/components';
-import { useSelect, useDispatch } from '@wordpress/data';
+import { useSelect } from '@wordpress/data';
/**
* Internal dependencies
@@ -52,13 +52,16 @@ export default function QuickInserter( {
( showPatterns && patterns.length > SEARCH_THRESHOLD ) ||
blockTypes.length > SEARCH_THRESHOLD;
- const { setInserterIsOpened, blockIndex } = useSelect(
+ const { setInserterIsOpened, insertionIndex } = useSelect(
( select ) => {
- const { getSettings, getBlockIndex } = select( blockEditorStore );
+ const { getSettings, getBlockIndex, getBlockCount } = select(
+ blockEditorStore
+ );
+ const index = getBlockIndex( clientId, rootClientId );
return {
setInserterIsOpened: getSettings()
.__experimentalSetIsInserterOpened,
- blockIndex: getBlockIndex( clientId, rootClientId ),
+ insertionIndex: index === -1 ? getBlockCount() : index,
};
},
[ clientId, rootClientId ]
@@ -70,13 +73,10 @@ export default function QuickInserter( {
}
}, [ setInserterIsOpened ] );
- const { __unstableSetInsertionPoint } = useDispatch( blockEditorStore );
-
// When clicking Browse All select the appropriate block so as
// the insertion point can work as expected
const onBrowseAll = () => {
- __unstableSetInsertionPoint( rootClientId, blockIndex );
- setInserterIsOpened( true );
+ setInserterIsOpened( { rootClientId, insertionIndex } );
};
return (
diff --git a/packages/block-editor/src/components/inserter/search-results.js b/packages/block-editor/src/components/inserter/search-results.js
index 03bf7b7c2da998..b29015ee763dc2 100644
--- a/packages/block-editor/src/components/inserter/search-results.js
+++ b/packages/block-editor/src/components/inserter/search-results.js
@@ -33,6 +33,7 @@ function InserterSearchResults( {
rootClientId,
clientId,
isAppender,
+ __experimentalInsertionIndex,
maxBlockPatterns,
maxBlockTypes,
showBlockDirectory = false,
@@ -46,6 +47,7 @@ function InserterSearchResults( {
rootClientId,
clientId,
isAppender,
+ insertionIndex: __experimentalInsertionIndex,
shouldFocusBlock,
} );
const [
diff --git a/packages/block-editor/src/store/actions.js b/packages/block-editor/src/store/actions.js
index b0144c19e4f476..823d1f6ba5c61b 100644
--- a/packages/block-editor/src/store/actions.js
+++ b/packages/block-editor/src/store/actions.js
@@ -620,34 +620,12 @@ export function* insertBlocks(
}
/**
- * Sets the insertion point without showing it to users.
+ * Returns an action object used in signalling that the insertion point should
+ * be shown.
*
- * Components like will default to inserting blocks at this point.
- *
- * @param {?string} rootClientId Root client ID of block list in which to
- * insert. Use `undefined` for the root block
- * list.
- * @param {number} index Index at which block should be inserted.
- *
- * @return {Object} Action object.
- */
-export function __unstableSetInsertionPoint( rootClientId, index ) {
- return {
- type: 'SET_INSERTION_POINT',
- rootClientId,
- index,
- };
-}
-
-/**
- * Sets the insertion point and shows it to users.
- *
- * Components like will default to inserting blocks at this point.
- *
- * @param {?string} rootClientId Root client ID of block list in which to
- * insert. Use `undefined` for the root block
- * list.
- * @param {number} index Index at which block should be inserted.
+ * @param {?string} rootClientId Optional root client ID of block list on
+ * which to insert.
+ * @param {?number} index Index at which block should be inserted.
*
* @return {Object} Action object.
*/
@@ -660,7 +638,7 @@ export function showInsertionPoint( rootClientId, index ) {
}
/**
- * Hides the insertion point for users.
+ * Returns an action object hiding the insertion point.
*
* @return {Object} Action object.
*/
diff --git a/packages/block-editor/src/store/reducer.js b/packages/block-editor/src/store/reducer.js
index b4349d621f7764..488272c145b277 100644
--- a/packages/block-editor/src/store/reducer.js
+++ b/packages/block-editor/src/store/reducer.js
@@ -1393,32 +1393,9 @@ export function blocksMode( state = {}, action ) {
}
/**
- * A helper for resetting the insertion point state.
- *
- * @param {Object} state Current state.
- * @param {Object} action Dispatched action.
- * @param {*} defaultValue The default value for the reducer.
- *
- * @return {*} Either the default value if a reset is required, or the state.
- */
-function resetInsertionPoint( state, action, defaultValue ) {
- switch ( action.type ) {
- case 'CLEAR_SELECTED_BLOCK':
- case 'SELECT_BLOCK':
- case 'SELECTION_CHANGE':
- case 'REPLACE_INNER_BLOCKS':
- case 'INSERT_BLOCKS':
- case 'REMOVE_BLOCKS':
- case 'REPLACE_BLOCKS':
- return defaultValue;
- }
-
- return state;
-}
-
-/**
- * Reducer returning the insertion point position, consisting of the
- * rootClientId and an index.
+ * Reducer returning the block insertion point visibility, either null if there
+ * is not an explicit insertion point assigned, or an object of its `index` and
+ * `rootClientId`.
*
* @param {Object} state Current state.
* @param {Object} action Dispatched action.
@@ -1427,33 +1404,15 @@ function resetInsertionPoint( state, action, defaultValue ) {
*/
export function insertionPoint( state = null, action ) {
switch ( action.type ) {
- case 'SET_INSERTION_POINT':
- case 'SHOW_INSERTION_POINT': {
+ case 'SHOW_INSERTION_POINT':
const { rootClientId, index } = action;
return { rootClientId, index };
- }
- }
-
- return resetInsertionPoint( state, action, null );
-}
-/**
- * Reducer returning the visibility of the insertion point.
- *
- * @param {Object} state Current state.
- * @param {Object} action Dispatched action.
- *
- * @return {Object} Updated state.
- */
-export function insertionPointVisibility( state = false, action ) {
- switch ( action.type ) {
- case 'SHOW_INSERTION_POINT':
- return true;
case 'HIDE_INSERTION_POINT':
- return false;
+ return null;
}
- return resetInsertionPoint( state, action, false );
+ return state;
}
/**
@@ -1764,7 +1723,6 @@ export default combineReducers( {
blocksMode,
blockListSettings,
insertionPoint,
- insertionPointVisibility,
template,
settings,
preferences,
diff --git a/packages/block-editor/src/store/selectors.js b/packages/block-editor/src/store/selectors.js
index 7d8b9d0b4cca80..564f6bd1a89709 100644
--- a/packages/block-editor/src/store/selectors.js
+++ b/packages/block-editor/src/store/selectors.js
@@ -1177,18 +1177,12 @@ export function isCaretWithinFormattedText( state ) {
}
/**
- * Returns the insertion point. This will be:
+ * Returns the insertion point, the index at which the new inserted block would
+ * be placed. Defaults to the last index.
*
- * 1) The insertion point manually set using setInsertionPoint() or
- * showInsertionPoint(); or
- * 2) The point after the current block selection, if there is a selection; or
- * 3) The point at the end of the block list.
- *
- * Components like will default to inserting blocks at this point.
- *
- * @param {Object} state Global application state.
+ * @param {Object} state Editor state.
*
- * @return {Object} Insertion point object with `rootClientId` and `index`.
+ * @return {Object} Insertion point object with `rootClientId`, `index`.
*/
export function getBlockInsertionPoint( state ) {
let rootClientId, index;
@@ -1214,15 +1208,14 @@ export function getBlockInsertionPoint( state ) {
}
/**
- * Whether or not the insertion point should be shown to users. This is set
- * using showInsertionPoint() or hideInsertionPoint().
+ * Returns true if we should show the block insertion point.
*
* @param {Object} state Global application state.
*
- * @return {?boolean} Whether the insertion point should be shown.
+ * @return {?boolean} Whether the insertion point is visible or not.
*/
export function isBlockInsertionPointVisible( state ) {
- return state.insertionPointVisibility;
+ return state.insertionPoint !== null;
}
/**
diff --git a/packages/block-editor/src/store/test/actions.js b/packages/block-editor/src/store/test/actions.js
index bbb47619ac28c8..6433f15e6523e7 100644
--- a/packages/block-editor/src/store/test/actions.js
+++ b/packages/block-editor/src/store/test/actions.js
@@ -42,7 +42,6 @@ const {
resetBlocks,
selectBlock,
selectPreviousBlock,
- __unstableSetInsertionPoint,
showInsertionPoint,
startMultiSelect,
startTyping,
@@ -741,31 +740,11 @@ describe( 'actions', () => {
} );
} );
- describe( '__unstableSetInsertionPoint', () => {
- it( 'should return the SET_INSERTION_POINT action', () => {
- expect( __unstableSetInsertionPoint() ).toEqual( {
- type: 'SET_INSERTION_POINT',
- } );
- expect( __unstableSetInsertionPoint( 'rootClientId', 2 ) ).toEqual(
- {
- type: 'SET_INSERTION_POINT',
- rootClientId: 'rootClientId',
- index: 2,
- }
- );
- } );
- } );
-
describe( 'showInsertionPoint', () => {
it( 'should return the SHOW_INSERTION_POINT action', () => {
expect( showInsertionPoint() ).toEqual( {
type: 'SHOW_INSERTION_POINT',
} );
- expect( showInsertionPoint( 'rootClientId', 2 ) ).toEqual( {
- type: 'SHOW_INSERTION_POINT',
- rootClientId: 'rootClientId',
- index: 2,
- } );
} );
} );
diff --git a/packages/block-editor/src/store/test/reducer.js b/packages/block-editor/src/store/test/reducer.js
index 13e6fe57ae9809..b4ad1c12ec1980 100644
--- a/packages/block-editor/src/store/test/reducer.js
+++ b/packages/block-editor/src/store/test/reducer.js
@@ -29,7 +29,6 @@ import {
preferences,
blocksMode,
insertionPoint,
- insertionPointVisibility,
template,
blockListSettings,
lastBlockAttributesChange,
@@ -2041,82 +2040,35 @@ describe( 'state', () => {
} );
describe( 'insertionPoint', () => {
- it( 'defaults to `null`', () => {
+ it( 'should default to null', () => {
const state = insertionPoint( undefined, {} );
- expect( state ).toEqual( null );
+ expect( state ).toBe( null );
} );
- it.each( [ 'SET_INSERTION_POINT', 'SHOW_INSERTION_POINT' ] )(
- 'sets the insertion point on %s',
- ( type ) => {
- const original = deepFreeze( {
- rootClientId: 'clientId1',
- index: 0,
- } );
-
- const expectedNewState = {
- rootClientId: 'clientId2',
- index: 1,
- };
-
- const state = insertionPoint( original, {
- type,
- ...expectedNewState,
- } );
-
- expect( state ).toEqual( expectedNewState );
- }
- );
-
- it.each( [
- 'CLEAR_SELECTED_BLOCK',
- 'SELECT_BLOCK',
- 'REPLACE_INNER_BLOCKS',
- 'INSERT_BLOCKS',
- 'REMOVE_BLOCKS',
- 'REPLACE_BLOCKS',
- ] )( 'resets the insertion point to `null` on %s', ( type ) => {
- const original = deepFreeze( {
+ it( 'should set insertion point', () => {
+ const state = insertionPoint( null, {
+ type: 'SHOW_INSERTION_POINT',
rootClientId: 'clientId1',
index: 0,
} );
- const state = insertionPoint( original, {
- type,
- } );
-
- expect( state ).toEqual( null );
- } );
- } );
-
- describe( 'insertionPointVisibility', () => {
- it( 'defaults to `false`', () => {
- const state = insertionPointVisibility( undefined, {} );
- expect( state ).toBe( false );
- } );
- it( 'shows the insertion point', () => {
- const state = insertionPointVisibility( false, {
- type: 'SHOW_INSERTION_POINT',
+ expect( state ).toEqual( {
+ rootClientId: 'clientId1',
+ index: 0,
} );
-
- expect( state ).toBe( true );
} );
- it.each( [
- 'HIDE_INSERTION_POINT',
- 'CLEAR_SELECTED_BLOCK',
- 'SELECT_BLOCK',
- 'REPLACE_INNER_BLOCKS',
- 'INSERT_BLOCKS',
- 'REMOVE_BLOCKS',
- 'REPLACE_BLOCKS',
- ] )( 'sets the insertion point on %s to `false`', ( type ) => {
- const state = insertionPointVisibility( true, {
- type,
+ it( 'should clear the insertion point', () => {
+ const original = deepFreeze( {
+ rootClientId: 'clientId1',
+ index: 0,
+ } );
+ const state = insertionPoint( original, {
+ type: 'HIDE_INSERTION_POINT',
} );
- expect( state ).toBe( false );
+ expect( state ).toBe( null );
} );
} );
diff --git a/packages/block-editor/src/store/test/selectors.js b/packages/block-editor/src/store/test/selectors.js
index 78f1342fa4ce64..5339ffb49943c2 100644
--- a/packages/block-editor/src/store/test/selectors.js
+++ b/packages/block-editor/src/store/test/selectors.js
@@ -2246,17 +2246,20 @@ describe( 'selectors', () => {
} );
describe( 'isBlockInsertionPointVisible', () => {
- it( 'should return false if insertion point is set to not show', () => {
+ it( 'should return false if no assigned insertion point', () => {
const state = {
- insertionPointVisibility: false,
+ insertionPoint: null,
};
expect( isBlockInsertionPointVisible( state ) ).toBe( false );
} );
- it( 'should return true if insertion point is set to show', () => {
+ it( 'should return true if assigned insertion point', () => {
const state = {
- insertionPointVisibility: true,
+ insertionPoint: {
+ rootClientId: undefined,
+ index: 5,
+ },
};
expect( isBlockInsertionPointVisible( state ) ).toBe( true );
diff --git a/packages/edit-post/src/components/layout/index.js b/packages/edit-post/src/components/layout/index.js
index 3bbee2c99851bf..e83613fccb0a29 100644
--- a/packages/edit-post/src/components/layout/index.js
+++ b/packages/edit-post/src/components/layout/index.js
@@ -86,6 +86,7 @@ function Layout( { styles } ) {
hasBlockSelected,
showMostUsedBlocks,
isInserterOpened,
+ insertionPoint,
showIconLabels,
hasReducedUI,
showBlockBreadcrumbs,
@@ -107,6 +108,9 @@ function Layout( { styles } ) {
'mostUsedBlocks'
),
isInserterOpened: select( editPostStore ).isInserterOpened(),
+ insertionPoint: select(
+ editPostStore
+ ).__experimentalGetInsertionPoint(),
mode: select( editPostStore ).getEditorMode(),
isRichEditingEnabled: editorSettings.richEditingEnabled,
hasActiveMetaboxes: select( editPostStore ).hasMetaBoxes(),
@@ -212,6 +216,10 @@ function Layout( { styles } ) {
showMostUsedBlocks={ showMostUsedBlocks }
showInserterHelpPanel
shouldFocusBlock={ isMobileViewport }
+ rootClientId={ insertionPoint.rootClientId }
+ __experimentalInsertionIndex={
+ insertionPoint.insertionIndex
+ }
/>
diff --git a/packages/edit-post/src/store/actions.js b/packages/edit-post/src/store/actions.js
index e8f4d1ab12d515..a7a55f7c352c8b 100644
--- a/packages/edit-post/src/store/actions.js
+++ b/packages/edit-post/src/store/actions.js
@@ -416,7 +416,13 @@ export function __experimentalSetPreviewDeviceType( deviceType ) {
/**
* Returns an action object used to open/close the inserter.
*
- * @param {boolean} value A boolean representing whether the inserter should be opened or closed.
+ * @param {boolean|Object} value Whether the inserter should be
+ * opened (true) or closed (false).
+ * To specify an insertion point,
+ * use an object.
+ * @param {string} value.rootClientId The root client ID to insert at.
+ * @param {number} value.insertionIndex The index to insert at.
+ *
* @return {Object} Action object.
*/
export function setIsInserterOpened( value ) {
diff --git a/packages/edit-post/src/store/reducer.js b/packages/edit-post/src/store/reducer.js
index 1f1e762f728135..318dcf4c53b1c8 100644
--- a/packages/edit-post/src/store/reducer.js
+++ b/packages/edit-post/src/store/reducer.js
@@ -241,10 +241,10 @@ export function deviceType( state = 'Desktop', action ) {
/**
* Reducer tracking whether the inserter is open.
*
- * @param {boolean} state
- * @param {Object} action
+ * @param {boolean|Object} state
+ * @param {Object} action
*/
-function isInserterOpened( state = false, action ) {
+function blockInserterPanel( state = false, action ) {
switch ( action.type ) {
case 'SET_IS_INSERTER_OPENED':
return action.value;
@@ -278,6 +278,6 @@ export default combineReducers( {
publishSidebarActive,
removedPanels,
deviceType,
- isInserterOpened,
+ blockInserterPanel,
isEditingTemplate,
} );
diff --git a/packages/edit-post/src/store/selectors.js b/packages/edit-post/src/store/selectors.js
index b734484b213953..eece40da2f56c0 100644
--- a/packages/edit-post/src/store/selectors.js
+++ b/packages/edit-post/src/store/selectors.js
@@ -324,7 +324,19 @@ export function __experimentalGetPreviewDeviceType( state ) {
* @return {boolean} Whether the inserter is opened.
*/
export function isInserterOpened( state ) {
- return state.isInserterOpened;
+ return !! state.blockInserterPanel;
+}
+
+/**
+ * Get the insertion point for the inserter.
+ *
+ * @param {Object} state Global application state.
+ *
+ * @return {Object} The root client ID and index to insert at.
+ */
+export function __experimentalGetInsertionPoint( state ) {
+ const { rootClientId, insertionIndex } = state.blockInserterPanel;
+ return { rootClientId, insertionIndex };
}
/**
diff --git a/packages/edit-site/src/components/secondary-sidebar/inserter-sidebar.js b/packages/edit-site/src/components/secondary-sidebar/inserter-sidebar.js
index 92381ff805983c..792a16bcb1aa93 100644
--- a/packages/edit-site/src/components/secondary-sidebar/inserter-sidebar.js
+++ b/packages/edit-site/src/components/secondary-sidebar/inserter-sidebar.js
@@ -1,7 +1,7 @@
/**
* WordPress dependencies
*/
-import { useDispatch } from '@wordpress/data';
+import { useSelect, useDispatch } from '@wordpress/data';
import { Button } from '@wordpress/components';
import { __experimentalLibrary as Library } from '@wordpress/block-editor';
import { close } from '@wordpress/icons';
@@ -17,6 +17,10 @@ import { store as editSiteStore } from '../../store';
export default function InserterSidebar() {
const { setIsInserterOpened } = useDispatch( editSiteStore );
+ const insertionPoint = useSelect(
+ ( select ) => select( editSiteStore ).__experimentalGetInsertionPoint(),
+ []
+ );
const isMobile = useViewportMatch( 'medium', '<' );
const [ inserterDialogRef, inserterDialogProps ] = useDialog( {
@@ -36,7 +40,14 @@ export default function InserterSidebar() {
/>
-
+
);
diff --git a/packages/edit-site/src/store/actions.js b/packages/edit-site/src/store/actions.js
index 4bad708c4f9131..17a0965ee7a53b 100644
--- a/packages/edit-site/src/store/actions.js
+++ b/packages/edit-site/src/store/actions.js
@@ -264,15 +264,21 @@ export function setIsNavigationPanelOpened( isOpen ) {
}
/**
- * Sets whether the block inserter panel should be open.
+ * Returns an action object used to open/close the inserter.
*
- * @param {boolean} isOpen If true, opens the inserter. If false, closes it. It
- * does not toggle the state, but sets it directly.
+ * @param {boolean|Object} value Whether the inserter should be
+ * opened (true) or closed (false).
+ * To specify an insertion point,
+ * use an object.
+ * @param {string} value.rootClientId The root client ID to insert at.
+ * @param {number} value.insertionIndex The index to insert at.
+ *
+ * @return {Object} Action object.
*/
-export function setIsInserterOpened( isOpen ) {
+export function setIsInserterOpened( value ) {
return {
type: 'SET_IS_INSERTER_OPENED',
- isOpen,
+ value,
};
}
diff --git a/packages/edit-site/src/store/reducer.js b/packages/edit-site/src/store/reducer.js
index 0e6c44f7bea240..01423f4f082d2b 100644
--- a/packages/edit-site/src/store/reducer.js
+++ b/packages/edit-site/src/store/reducer.js
@@ -145,13 +145,18 @@ export function navigationPanel(
menu: ! action.isOpen ? MENU_ROOT : state.menu, // Set menu to root when closing panel.
isOpen: action.isOpen,
};
- case 'SET_IS_INSERTER_OPENED':
case 'SET_IS_LIST_VIEW_OPENED':
return {
...state,
menu: state.isOpen && action.isOpen ? MENU_ROOT : state.menu, // Set menu to root when closing panel.
isOpen: action.isOpen ? false : state.isOpen,
};
+ case 'SET_IS_INSERTER_OPENED':
+ return {
+ ...state,
+ menu: state.isOpen && action.value ? MENU_ROOT : state.menu, // Set menu to root when closing panel.
+ isOpen: action.value ? false : state.isOpen,
+ };
}
return state;
}
@@ -162,8 +167,8 @@ export function navigationPanel(
* Note: this reducer interacts with the navigation and list view panels reducers
* to make sure that only one of the three panels is open at the same time.
*
- * @param {Object} state Current state.
- * @param {Object} action Dispatched action.
+ * @param {boolean|Object} state Current state.
+ * @param {Object} action Dispatched action.
*/
export function blockInserterPanel( state = false, action ) {
switch ( action.type ) {
@@ -173,7 +178,7 @@ export function blockInserterPanel( state = false, action ) {
case 'SET_IS_LIST_VIEW_OPENED':
return action.isOpen ? false : state;
case 'SET_IS_INSERTER_OPENED':
- return action.isOpen;
+ return action.value;
}
return state;
}
@@ -192,8 +197,9 @@ export function listViewPanel( state = false, action ) {
case 'OPEN_NAVIGATION_PANEL_TO_MENU':
return false;
case 'SET_IS_NAVIGATION_PANEL_OPENED':
- case 'SET_IS_INSERTER_OPENED':
return action.isOpen ? false : state;
+ case 'SET_IS_INSERTER_OPENED':
+ return action.value ? false : state;
case 'SET_IS_LIST_VIEW_OPENED':
return action.isOpen;
}
diff --git a/packages/edit-site/src/store/selectors.js b/packages/edit-site/src/store/selectors.js
index 8543eb233fe035..16f1a711cd2331 100644
--- a/packages/edit-site/src/store/selectors.js
+++ b/packages/edit-site/src/store/selectors.js
@@ -231,7 +231,19 @@ export function isNavigationOpened( state ) {
* @return {boolean} True if the inserter panel should be open; false if closed.
*/
export function isInserterOpened( state ) {
- return state.blockInserterPanel;
+ return !! state.blockInserterPanel;
+}
+
+/**
+ * Get the insertion point for the inserter.
+ *
+ * @param {Object} state Global application state.
+ *
+ * @return {Object} The root client ID and index to insert at.
+ */
+export function __experimentalGetInsertionPoint( state ) {
+ const { rootClientId, insertionIndex } = state.blockInserterPanel;
+ return { rootClientId, insertionIndex };
}
/**
diff --git a/packages/edit-widgets/src/store/actions.js b/packages/edit-widgets/src/store/actions.js
index 9c5b86924e2908..5a9d7d25e2ebc4 100644
--- a/packages/edit-widgets/src/store/actions.js
+++ b/packages/edit-widgets/src/store/actions.js
@@ -299,7 +299,13 @@ export function setIsWidgetAreaOpen( clientId, isOpen ) {
/**
* Returns an action object used to open/close the inserter.
*
- * @param {boolean} value A boolean representing whether the inserter should be opened or closed.
+ * @param {boolean|Object} value Whether the inserter should be
+ * opened (true) or closed (false).
+ * To specify an insertion point,
+ * use an object.
+ * @param {string} value.rootClientId The root client ID to insert at.
+ * @param {number} value.insertionIndex The index to insert at.
+ *
* @return {Object} Action object.
*/
export function setIsInserterOpened( value ) {
diff --git a/packages/edit-widgets/src/store/reducer.js b/packages/edit-widgets/src/store/reducer.js
index 93e650c88769f9..d6af45e6112091 100644
--- a/packages/edit-widgets/src/store/reducer.js
+++ b/packages/edit-widgets/src/store/reducer.js
@@ -32,10 +32,10 @@ export function widgetAreasOpenState( state = {}, action ) {
/**
* Reducer tracking whether the inserter is open.
*
- * @param {boolean} state
- * @param {Object} action
+ * @param {boolean|Object} state
+ * @param {Object} action
*/
-function isInserterOpened( state = false, action ) {
+function blockInserterPanel( state = false, action ) {
switch ( action.type ) {
case 'SET_IS_INSERTER_OPENED':
return action.value;
@@ -44,6 +44,6 @@ function isInserterOpened( state = false, action ) {
}
export default combineReducers( {
- isInserterOpened,
+ blockInserterPanel,
widgetAreasOpenState,
} );
diff --git a/packages/edit-widgets/src/store/selectors.js b/packages/edit-widgets/src/store/selectors.js
index 44d0f4614f7f99..1d8cc005148f2f 100644
--- a/packages/edit-widgets/src/store/selectors.js
+++ b/packages/edit-widgets/src/store/selectors.js
@@ -193,5 +193,5 @@ export const getIsWidgetAreaOpen = ( state, clientId ) => {
* @return {boolean} Whether the inserter is opened.
*/
export function isInserterOpened( state ) {
- return state.isInserterOpened;
+ return !! state.blockInserterPanel;
}