Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce the layout prop to InnerBlocks #26380

Merged
merged 2 commits into from
Oct 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
*/
import { __ } from '@wordpress/i18n';
import { ToolbarGroup } from '@wordpress/components';
import { withSelect } from '@wordpress/data';
import { compose } from '@wordpress/compose';
import { useSelect } from '@wordpress/data';
import {
positionCenter,
positionLeft,
Expand All @@ -13,6 +12,11 @@ import {
stretchWide,
} from '@wordpress/icons';

/**
* Internal dependencies
*/
import { useLayout } from '../inner-blocks/layout';

const BLOCK_ALIGNMENTS_CONTROLS = {
left: {
icon: positionLeft,
Expand Down Expand Up @@ -49,18 +53,36 @@ export function BlockAlignmentToolbar( {
onChange,
controls = DEFAULT_CONTROLS,
isCollapsed = true,
wideControlsEnabled = false,
} ) {
const { wideControlsEnabled = false } = useSelect( ( select ) => {
const { getSettings } = select( 'core/block-editor' );
const settings = getSettings();
return {
wideControlsEnabled: settings.alignWide,
};
} );
const layout = useLayout();
const supportsAlignments = layout.type === 'default';
Copy link
Contributor

@ntsekouras ntsekouras Oct 22, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to check the type === default and not check explicitly for alignments. I'm trying to understand your changes (haven't thoroughly yet :) )

In my head for now, I understand that we could have the new property layout filled with any property we would like and handle that new property per Block/use case.

For example if I would like to have a grid layout, should I add something like:

__experimentalLayout: { type: 'grid', ...other options }

or just

__experimentalLayout: { grid: {  columns: 3 } }

Am I missing the concept entirely?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exactly and other types of layouts might not have "alignments" support at all, so we bail out early for these.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure where your exactly goes :) That I'm missing the concept or is related in something for the above grid examples? :)

I still didn't understand if for checking alignment, we would need both type and another property alignments, or just one property alignments would be enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alignments might not even exist in some layouts, the shape of the "layout" object depends on the type. Also, alignments on other layouts could have a completely different meaning. Basically the alignments as we know them today only make sense in the default layout, so we need to check the type first.


if ( ! supportsAlignments ) {
return null;
}

const { alignments: availableAlignments = DEFAULT_CONTROLS } = layout;
const enabledControls = controls.filter(
( control ) =>
( wideControlsEnabled || ! WIDE_CONTROLS.includes( control ) ) &&
availableAlignments.includes( control )
);

if ( enabledControls.length === 0 ) {
return null;
}

function applyOrUnset( align ) {
return () => onChange( value === align ? undefined : align );
}

const enabledControls = wideControlsEnabled
? controls
: controls.filter(
( control ) => WIDE_CONTROLS.indexOf( control ) === -1
);

const activeAlignmentControl = BLOCK_ALIGNMENTS_CONTROLS[ value ];
const defaultAlignmentControl =
BLOCK_ALIGNMENTS_CONTROLS[ DEFAULT_CONTROL ];
Expand All @@ -87,12 +109,4 @@ export function BlockAlignmentToolbar( {
);
}

export default compose(
withSelect( ( select ) => {
const { getSettings } = select( 'core/block-editor' );
const settings = getSettings();
return {
wideControlsEnabled: settings.alignWide,
};
} )
)( BlockAlignmentToolbar );
export default BlockAlignmentToolbar;
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,23 @@
*/
import { shallow } from 'enzyme';

/**
* WordPress dependencies
*/
import { useSelect } from '@wordpress/data';

/**
* Internal dependencies
*/
import { BlockAlignmentToolbar } from '../';

jest.mock( '@wordpress/data/src/components/use-select', () => {
// This allows us to tweak the returned value on each test
const mock = jest.fn();
return mock;
} );
useSelect.mockImplementation( () => ( { wideControlsEnabled: false } ) );

describe( 'BlockAlignmentToolbar', () => {
const alignment = 'left';
const onChange = jest.fn();
Expand Down
24 changes: 15 additions & 9 deletions packages/block-editor/src/components/inner-blocks/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import { BlockListItems } from '../block-list';
import { BlockContextProvider } from '../block-context';
import { useBlockEditContext } from '../block-edit/context';
import useBlockSync from '../provider/use-block-sync';
import { defaultLayout, LayoutProvider } from './layout';

/**
* InnerBlocks is a component which allows a single block to have multiple blocks
Expand All @@ -49,6 +50,7 @@ function UncontrolledInnerBlocks( props ) {
renderAppender,
orientation,
placeholder,
__experimentalLayout: layout = defaultLayout,
} = props;

useNestedSettingsUpdate(
Expand Down Expand Up @@ -83,15 +85,19 @@ function UncontrolledInnerBlocks( props ) {
// This component needs to always be synchronous as it's the one changing
// the async mode depending on the block selection.
return (
<BlockContextProvider value={ context }>
<BlockListItems
rootClientId={ clientId }
renderAppender={ renderAppender }
__experimentalAppenderTagName={ __experimentalAppenderTagName }
wrapperRef={ wrapperRef }
placeholder={ placeholder }
/>
</BlockContextProvider>
<LayoutProvider value={ layout }>
<BlockContextProvider value={ context }>
<BlockListItems
rootClientId={ clientId }
renderAppender={ renderAppender }
__experimentalAppenderTagName={
__experimentalAppenderTagName
}
wrapperRef={ wrapperRef }
placeholder={ placeholder }
/>
</BlockContextProvider>
</LayoutProvider>
);
}

Expand Down
20 changes: 20 additions & 0 deletions packages/block-editor/src/components/inner-blocks/layout.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* WordPress dependencies
*/
import { createContext, useContext } from '@wordpress/element';

export const defaultLayout = { type: 'default' };

const Layout = createContext( defaultLayout );

/**
* Allows to define the layout.
*/
export const LayoutProvider = Layout.Provider;

/**
* React hook used to retrieve the layout config.
*/
export function useLayout() {
return useContext( Layout );
}
24 changes: 7 additions & 17 deletions packages/block-editor/src/hooks/align.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import { has, without } from 'lodash';
/**
* WordPress dependencies
*/
import { createContext, useContext } from '@wordpress/element';
import { createHigherOrderComponent } from '@wordpress/compose';
import { addFilter } from '@wordpress/hooks';
import {
Expand Down Expand Up @@ -106,13 +105,6 @@ export function addAttribute( settings ) {
return settings;
}

const AlignmentHookSettings = createContext( {} );

/**
* Allows to pass additional settings to the alignment hook.
*/
export const AlignmentHookSettingsProvider = AlignmentHookSettings.Provider;

/**
* Override the default edit UI to include new toolbar controls for block
* alignment, if block defines support.
Expand All @@ -122,17 +114,15 @@ export const AlignmentHookSettingsProvider = AlignmentHookSettings.Provider;
*/
export const withToolbarControls = createHigherOrderComponent(
( BlockEdit ) => ( props ) => {
const { isEmbedButton } = useContext( AlignmentHookSettings );
const { name: blockName } = props;
// Compute valid alignments without taking into account,
// if the theme supports wide alignments or not.
// BlockAlignmentToolbar takes into account the theme support.
const validAlignments = isEmbedButton
? []
: getValidAlignments(
getBlockSupport( blockName, 'align' ),
hasBlockSupport( blockName, 'alignWide', true )
);
// if the theme supports wide alignments or not
// and without checking the layout for availble alignments.
// BlockAlignmentToolbar takes both of these into account.
const validAlignments = getValidAlignments(
getBlockSupport( blockName, 'align' ),
hasBlockSupport( blockName, 'alignWide', true )
);

const updateAlignment = ( nextAlign ) => {
if ( ! nextAlign ) {
Expand Down
2 changes: 0 additions & 2 deletions packages/block-editor/src/hooks/align.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ import { WIDE_ALIGNMENTS } from '@wordpress/components';

const ALIGNMENTS = [ 'left', 'center', 'right' ];

export { AlignmentHookSettingsProvider } from './align.js';

// Used to filter out blocks that don't support wide/full alignment on mobile
addFilter(
'blocks.registerBlockType',
Expand Down
4 changes: 1 addition & 3 deletions packages/block-editor/src/hooks/index.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
/**
* Internal dependencies
*/
import { AlignmentHookSettingsProvider } from './align';
import './align';
import './anchor';
import './custom-class-name';
import './generated-class-name';
import './style';
import './color';
import './font-size';

export { AlignmentHookSettingsProvider };
4 changes: 1 addition & 3 deletions packages/block-editor/src/hooks/index.native.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
/**
* Internal dependencies
*/
import { AlignmentHookSettingsProvider } from './align';
import './align';
import './anchor';
import './custom-class-name';
import './generated-class-name';
import './style';
import './color';
import './font-size';

export { AlignmentHookSettingsProvider };
3 changes: 1 addition & 2 deletions packages/block-editor/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import '@wordpress/notices';
/**
* Internal dependencies
*/
import { AlignmentHookSettingsProvider as __experimentalAlignmentHookSettingsProvider } from './hooks';
export { __experimentalAlignmentHookSettingsProvider };
import './hooks';
export * from './components';
export * from './utils';
export { storeConfig } from './store';
Expand Down
16 changes: 5 additions & 11 deletions packages/block-library/src/buttons/edit.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
* WordPress dependencies
*/
import {
__experimentalAlignmentHookSettingsProvider as AlignmentHookSettingsProvider,
__experimentalUseInnerBlocksProps as useInnerBlocksProps,
useBlockProps,
} from '@wordpress/block-editor';
Expand All @@ -15,23 +14,18 @@ import { name as buttonBlockName } from '../button/';
const ALLOWED_BLOCKS = [ buttonBlockName ];
const BUTTONS_TEMPLATE = [ [ 'core/button' ] ];

// Inside buttons block alignment options are not supported.
const alignmentHooksSetting = {
isEmbedButton: true,
};

function ButtonsEdit() {
const blockProps = useBlockProps();
const innerBlocksProps = useInnerBlocksProps( blockProps, {
allowedBlocks: ALLOWED_BLOCKS,
template: BUTTONS_TEMPLATE,
orientation: 'horizontal',
__experimentalLayout: {
type: 'default',
alignments: [],
},
} );
return (
<AlignmentHookSettingsProvider value={ alignmentHooksSetting }>
<div { ...innerBlocksProps } />
</AlignmentHookSettingsProvider>
);
return <div { ...innerBlocksProps } />;
}

export default ButtonsEdit;
15 changes: 4 additions & 11 deletions packages/block-library/src/buttons/edit.native.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,7 @@ import { View } from 'react-native';
/**
* WordPress dependencies
*/
import {
__experimentalAlignmentHookSettingsProvider as AlignmentHookSettingsProvider,
InnerBlocks,
} from '@wordpress/block-editor';
import { InnerBlocks } from '@wordpress/block-editor';
import { createBlock } from '@wordpress/blocks';
import { useResizeObserver } from '@wordpress/compose';
import { useDispatch, useSelect } from '@wordpress/data';
Expand Down Expand Up @@ -97,15 +94,10 @@ export default function ButtonsEdit( {
</View>
) );

// Inside buttons block alignment options are not supported.
const alignmentHooksSetting = {
isEmbedButton: true,
};

const shouldRenderFooterAppender = isSelected || isInnerButtonSelected;

return (
<AlignmentHookSettingsProvider value={ alignmentHooksSetting }>
<>
{ resizeObserver }
<InnerBlocks
allowedBlocks={ ALLOWED_BLOCKS }
Expand All @@ -122,7 +114,8 @@ export default function ButtonsEdit( {
parentWidth={ maxWidth }
marginHorizontal={ spacing }
marginVertical={ spacing }
__experimentalLayout={ { type: 'default', alignments: [] } }
/>
</AlignmentHookSettingsProvider>
</>
);
}