Skip to content

Commit

Permalink
Add __experimentalDefaultBlock setting to block list settings to allo…
Browse files Browse the repository at this point in the history
…w insertion of elements before and after a block, when the default block is not supported in the parent container.
  • Loading branch information
gwwar committed Sep 21, 2021
1 parent b12bbe4 commit d283507
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 13 deletions.
3 changes: 2 additions & 1 deletion docs/reference-guides/data/data-core-block-editor.md
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,8 @@ _Returns_

### getBlockHierarchyRootClientId

Given a block client ID, returns the root of the hierarchy from which the block is nested, return the block itself for root level blocks.
Given a block client ID, returns the root of the hierarchy from which the block is nested, return the block itself
for root level blocks.

_Parameters_

Expand Down
7 changes: 4 additions & 3 deletions packages/block-editor/src/components/block-actions/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,9 @@ export default function BlockActions( {
getBlocksByClientId,
canRemoveBlocks,
getTemplateLock,
__experimentalGetDefaultBlockForAllowedBlocks,
} = useSelect( ( select ) => select( blockEditorStore ), [] );
const { getDefaultBlockName, getGroupingBlockName } = useSelect(
const { getGroupingBlockName } = useSelect(
( select ) => select( blocksStore ),
[]
);
Expand All @@ -46,11 +47,11 @@ export default function BlockActions( {
);
} );

const canInsertDefaultBlock = canInsertBlockType(
getDefaultBlockName(),
const defaultBlock = __experimentalGetDefaultBlockForAllowedBlocks(
rootClientId
);

const canInsertDefaultBlock = !! defaultBlock;
const canRemove = canRemoveBlocks( clientIds, rootClientId );

const {
Expand Down
4 changes: 3 additions & 1 deletion packages/block-editor/src/components/inner-blocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ function UncontrolledInnerBlocks( props ) {
orientation,
placeholder,
__experimentalLayout,
__experimentalDefaultBlock,
} = props;

useNestedSettingsUpdate(
Expand All @@ -60,7 +61,8 @@ function UncontrolledInnerBlocks( props ) {
templateLock,
captureToolbars,
orientation,
__experimentalLayout
__experimentalLayout,
__experimentalDefaultBlock
);

useInnerBlockTemplateSync(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,19 @@ import { getLayoutType } from '../../layouts';
* @param {string} orientation The direction in which the block
* should face.
* @param {Object} layout The layout object for the block container.
*
* @param {[]} __experimentalDefaultBlock The default block: [ blockName, { blockAttributes } ].
* Used to insert blocks of this type, before/after blocks
* in inner blocks.
*/
export default function useNestedSettingsUpdate(
clientId,
allowedBlocks,
templateLock,
captureToolbars,
orientation,
layout
layout,
__experimentalDefaultBlock
) {
const { updateBlockListSettings } = useDispatch( blockEditorStore );

Expand Down Expand Up @@ -64,6 +69,7 @@ export default function useNestedSettingsUpdate(
useLayoutEffect( () => {
const newSettings = {
allowedBlocks: _allowedBlocks,
__experimentalDefaultBlock,
templateLock:
templateLock === undefined ? parentLock : templateLock,
};
Expand Down
28 changes: 22 additions & 6 deletions packages/block-editor/src/store/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import {
createBlock,
doBlocksMatchTemplate,
getBlockType,
getDefaultBlockName,
hasBlockSupport,
switchToBlockType,
synchronizeBlocksWithTemplate,
Expand Down Expand Up @@ -1131,16 +1130,33 @@ export function selectionChange(
*
* @return {Object} Action object
*/
export function insertDefaultBlock( attributes, rootClientId, index ) {
export function* insertDefaultBlock( attributes = {}, rootClientId, index ) {
// See if we specified a default for allowed blocks
const defaultBlock = yield controls.select(
blockEditorStoreName,
'__experimentalGetDefaultBlockForAllowedBlocks',
rootClientId
);

// Abort if there is no default block type (if it has been unregistered).
const defaultBlockName = getDefaultBlockName();
if ( ! defaultBlockName ) {
if ( ! defaultBlock ) {
return;
}

const block = createBlock( defaultBlockName, attributes );
const [ defaultBlockName, defaultBlockAttributes ] = defaultBlock;

// prefer the non-empty block attributes
let blockAttributes = attributes;
if (
Object.keys( attributes ).length === 0 &&
Object.keys( defaultBlockAttributes ).length > 0
) {
blockAttributes = defaultBlockAttributes;
}

const block = createBlock( defaultBlockName, blockAttributes );

return insertBlock( block, index, rootClientId );
return yield insertBlock( block, index, rootClientId );
}

/**
Expand Down
30 changes: 29 additions & 1 deletion packages/block-editor/src/store/selectors.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import createSelector from 'rememo';
import {
getBlockType,
getBlockTypes,
getDefaultBlockName,
hasBlockSupport,
getPossibleBlockTransformations,
parse,
Expand Down Expand Up @@ -499,7 +500,8 @@ export const getBlockParentsByBlockName = createSelector(
);

/**
* Given a block client ID, returns the root of the hierarchy from which the block is nested, return the block itself for root level blocks.
* Given a block client ID, returns the root of the hierarchy from which the block is nested, return the block itself
* for root level blocks.
*
* @param {Object} state Editor state.
* @param {string} clientId Block from which to find root client ID.
Expand Down Expand Up @@ -1991,6 +1993,32 @@ export function getBlockListSettings( state, clientId ) {
return state.blockListSettings[ clientId ];
}

/**
* Returns the default block name for a list of allowed blocks, if any exist.
*
* @param {Object} state Editor state.
* @param {?string} clientId Block client ID.
*
* @return {?[]} default block, [ blockName, { blockAttributes } ].
*/
export function __experimentalGetDefaultBlockForAllowedBlocks(
state,
clientId
) {
const settings = getBlockListSettings( state, clientId );

const [
blockName,
blockAttributes = {},
] = settings?.__experimentalDefaultBlock ?? [ getDefaultBlockName() ];

if ( ! canInsertBlockType( state, blockName, clientId ) ) {
return;
}

return [ blockName, blockAttributes ];
}

/**
* Returns the editor settings.
*
Expand Down
18 changes: 18 additions & 0 deletions packages/block-editor/src/store/test/actions.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const {
hideInsertionPoint,
insertBlock,
insertBlocks,
insertDefaultBlock,
mergeBlocks,
moveBlocksToPosition,
multiSelect,
Expand Down Expand Up @@ -459,6 +460,23 @@ describe( 'actions', () => {
} );
} );

describe( 'insertDefaultBlock', () => {
it( 'should check for allowed default block', () => {
const insertDefaultBlockGenerator = insertDefaultBlock(
{},
'testclientid',
0
);
expect( insertDefaultBlockGenerator.next().value ).toEqual(
controls.select(
blockEditorStoreName,
'__experimentalGetDefaultBlockForAllowedBlocks',
'testclientid'
)
);
} );
} );

describe( 'insertBlocks', () => {
it( 'should apply default styles to blocks if blocks do not contain a style', () => {
const ribsBlock = {
Expand Down
Loading

0 comments on commit d283507

Please sign in to comment.