Cart i2: view switcher shared to children (https://github.com/woocommerce/woocommerce-blocks/pull/4817)
* Replace context with __experimentalShareWithChildBlocks * Switch to parent block when changing views * Swap order of views * Drop default, use first view * Improve block selection after changing views
This commit is contained in:
parent
8e38c6b857
commit
1aaa00ed2a
|
@ -6,22 +6,14 @@ import { createContext, useContext } from '@wordpress/element';
|
|||
/**
|
||||
* Context consumed by inner blocks.
|
||||
*/
|
||||
export type CartBlockControlsContextProps = {
|
||||
viewSwitcher: {
|
||||
component: () => JSX.Element | null;
|
||||
currentView: string;
|
||||
};
|
||||
export type CartBlockContextProps = {
|
||||
currentView: string;
|
||||
};
|
||||
|
||||
export const CartBlockControlsContext = createContext<
|
||||
CartBlockControlsContextProps
|
||||
>( {
|
||||
viewSwitcher: {
|
||||
component: () => null,
|
||||
currentView: 'filledCart',
|
||||
},
|
||||
export const CartBlockContext = createContext< CartBlockContextProps >( {
|
||||
currentView: '',
|
||||
} );
|
||||
|
||||
export const useCartBlockControlsContext = (): CartBlockControlsContextProps => {
|
||||
return useContext( CartBlockControlsContext );
|
||||
export const useCartBlockContext = (): CartBlockContextProps => {
|
||||
return useContext( CartBlockContext );
|
||||
};
|
||||
|
|
|
@ -6,9 +6,10 @@ import classnames from 'classnames';
|
|||
import { __ } from '@wordpress/i18n';
|
||||
import { CartCheckoutFeedbackPrompt } from '@woocommerce/editor-components/feedback-prompt';
|
||||
import {
|
||||
InnerBlocks,
|
||||
useBlockProps,
|
||||
InnerBlocks,
|
||||
InspectorControls,
|
||||
BlockControls,
|
||||
} from '@wordpress/block-editor';
|
||||
import { PanelBody, ToggleControl, Notice } from '@wordpress/components';
|
||||
import { CartCheckoutCompatibilityNotice } from '@woocommerce/editor-components/compatibility-notices';
|
||||
|
@ -31,7 +32,7 @@ import './editor.scss';
|
|||
import { addClassToBody, useBlockPropsWithLocking } from './hacks';
|
||||
import { useViewSwitcher } from './use-view-switcher';
|
||||
import type { Attributes } from './types';
|
||||
import { CartBlockControlsContext } from './context';
|
||||
import { CartBlockContext } from './context';
|
||||
|
||||
// This is adds a class to body to signal if the selected block is locked
|
||||
addClassToBody();
|
||||
|
@ -140,24 +141,28 @@ export const Edit = ( {
|
|||
className,
|
||||
attributes,
|
||||
setAttributes,
|
||||
clientId,
|
||||
}: {
|
||||
className: string;
|
||||
attributes: Attributes;
|
||||
setAttributes: ( attributes: Record< string, unknown > ) => undefined;
|
||||
clientId: string;
|
||||
} ): JSX.Element => {
|
||||
const { currentView, component: ViewSwitcherComponent } = useViewSwitcher( [
|
||||
{
|
||||
view: 'emptyCart',
|
||||
label: __( 'Empty Cart', 'woo-gutenberg-products-block' ),
|
||||
icon: <Icon srcElement={ removeCart } />,
|
||||
},
|
||||
{
|
||||
view: 'filledCart',
|
||||
label: __( 'Filled Cart', 'woo-gutenberg-products-block' ),
|
||||
icon: <Icon srcElement={ filledCart } />,
|
||||
default: true,
|
||||
},
|
||||
] );
|
||||
const { currentView, component: ViewSwitcherComponent } = useViewSwitcher(
|
||||
clientId,
|
||||
[
|
||||
{
|
||||
view: 'woocommerce/filled-cart-block',
|
||||
label: __( 'Filled Cart', 'woo-gutenberg-products-block' ),
|
||||
icon: <Icon srcElement={ filledCart } />,
|
||||
},
|
||||
{
|
||||
view: 'woocommerce/empty-cart-block',
|
||||
label: __( 'Empty Cart', 'woo-gutenberg-products-block' ),
|
||||
icon: <Icon srcElement={ removeCart } />,
|
||||
},
|
||||
]
|
||||
);
|
||||
const cartClassName = classnames( {
|
||||
'has-dark-controls': attributes.hasDarkControls,
|
||||
} );
|
||||
|
@ -212,13 +217,12 @@ export const Edit = ( {
|
|||
attributes={ attributes }
|
||||
setAttributes={ setAttributes }
|
||||
/>
|
||||
<ViewSwitcherComponent />
|
||||
<CartBlockControlsContext.Provider
|
||||
<BlockControls __experimentalShareWithChildBlocks>
|
||||
<ViewSwitcherComponent />
|
||||
</BlockControls>
|
||||
<CartBlockContext.Provider
|
||||
value={ {
|
||||
viewSwitcher: {
|
||||
component: ViewSwitcherComponent,
|
||||
currentView,
|
||||
},
|
||||
currentView,
|
||||
} }
|
||||
>
|
||||
<CartProvider>
|
||||
|
@ -230,7 +234,7 @@ export const Edit = ( {
|
|||
/>
|
||||
</div>
|
||||
</CartProvider>
|
||||
</CartBlockControlsContext.Provider>
|
||||
</CartBlockContext.Provider>
|
||||
</EditorProvider>
|
||||
</BlockErrorBoundary>
|
||||
<CartCheckoutCompatibilityNotice blockName="cart" />
|
||||
|
|
|
@ -29,6 +29,7 @@ const settings = {
|
|||
align: false,
|
||||
html: false,
|
||||
multiple: false,
|
||||
__experimentalExposeControlsToChildren: true,
|
||||
},
|
||||
example: {
|
||||
attributes: {
|
||||
|
|
|
@ -9,10 +9,11 @@ import { innerBlockAreas } from '@woocommerce/blocks-checkout';
|
|||
*/
|
||||
import { useForcedLayout } from '../../use-forced-layout';
|
||||
import { getAllowedBlocks } from '../../editor-utils';
|
||||
import { useCartBlockControlsContext } from '../../context';
|
||||
import { useCartBlockContext } from '../../context';
|
||||
|
||||
export const Edit = ( { clientId }: { clientId: string } ): JSX.Element => {
|
||||
const blockProps = useBlockProps();
|
||||
const { currentView } = useCartBlockContext();
|
||||
const allowedBlocks = getAllowedBlocks( innerBlockAreas.EMPTY_CART );
|
||||
|
||||
useForcedLayout( {
|
||||
|
@ -20,18 +21,16 @@ export const Edit = ( { clientId }: { clientId: string } ): JSX.Element => {
|
|||
template: allowedBlocks,
|
||||
} );
|
||||
|
||||
const {
|
||||
viewSwitcher: { currentView, component: ViewSwitcherComponent },
|
||||
} = useCartBlockControlsContext();
|
||||
|
||||
return (
|
||||
<div { ...blockProps } hidden={ currentView !== 'emptyCart' }>
|
||||
<div
|
||||
{ ...blockProps }
|
||||
hidden={ currentView !== 'woocommerce/empty-cart-block' }
|
||||
>
|
||||
This is the empty cart block.
|
||||
<InnerBlocks
|
||||
allowedBlocks={ allowedBlocks }
|
||||
templateLock={ false }
|
||||
/>
|
||||
<ViewSwitcherComponent />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -12,23 +12,22 @@ import { useForcedLayout } from '../../use-forced-layout';
|
|||
import { getAllowedBlocks } from '../../editor-utils';
|
||||
import { Columns } from './../../columns';
|
||||
import './editor.scss';
|
||||
import { useCartBlockControlsContext } from '../../context';
|
||||
import { useCartBlockContext } from '../../context';
|
||||
|
||||
export const Edit = ( { clientId }: { clientId: string } ): JSX.Element => {
|
||||
const blockProps = useBlockProps();
|
||||
const { currentView } = useCartBlockContext();
|
||||
const allowedBlocks = getAllowedBlocks( innerBlockAreas.FILLED_CART );
|
||||
|
||||
useForcedLayout( {
|
||||
clientId,
|
||||
template: allowedBlocks,
|
||||
} );
|
||||
|
||||
const {
|
||||
viewSwitcher: { currentView, component: ViewSwitcherComponent },
|
||||
} = useCartBlockControlsContext();
|
||||
|
||||
return (
|
||||
<div { ...blockProps } hidden={ currentView !== 'filledCart' }>
|
||||
<div
|
||||
{ ...blockProps }
|
||||
hidden={ currentView !== 'woocommerce/filled-cart-block' }
|
||||
>
|
||||
<Columns>
|
||||
<SidebarLayout className={ 'wc-block-cart' }>
|
||||
<InnerBlocks
|
||||
|
@ -37,7 +36,6 @@ export const Edit = ( { clientId }: { clientId: string } ): JSX.Element => {
|
|||
/>
|
||||
</SidebarLayout>
|
||||
</Columns>
|
||||
<ViewSwitcherComponent />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -3,50 +3,52 @@
|
|||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useState } from '@wordpress/element';
|
||||
import { useDispatch, select } from '@wordpress/data';
|
||||
import { Toolbar, ToolbarDropdownMenu } from '@wordpress/components';
|
||||
import { BlockControls } from '@wordpress/block-editor';
|
||||
import { Icon, eye } from '@woocommerce/icons';
|
||||
import { store as blockEditorStore } from '@wordpress/block-editor';
|
||||
|
||||
interface View {
|
||||
view: string;
|
||||
label: string;
|
||||
icon: string | JSX.Element;
|
||||
default?: boolean;
|
||||
}
|
||||
|
||||
export const useViewSwitcher = (
|
||||
clientId: string,
|
||||
views: View[]
|
||||
): {
|
||||
currentView: string;
|
||||
component: () => JSX.Element;
|
||||
} => {
|
||||
const initialView =
|
||||
views?.find( ( view ) => view.default === true ) || views[ 0 ];
|
||||
const initialView = views[ 0 ];
|
||||
const [ currentView, setCurrentView ] = useState( initialView );
|
||||
const { selectBlock } = useDispatch( 'core/block-editor' );
|
||||
const { getBlock } = select( blockEditorStore );
|
||||
|
||||
const ViewSwitcherComponent = () => (
|
||||
<BlockControls>
|
||||
<Toolbar>
|
||||
<ToolbarDropdownMenu
|
||||
label={ __(
|
||||
'Switch view',
|
||||
'woo-gutenberg-products-block'
|
||||
) }
|
||||
text={ currentView.label }
|
||||
icon={
|
||||
<Icon
|
||||
srcElement={ eye }
|
||||
style={ { marginRight: '8px' } }
|
||||
/>
|
||||
}
|
||||
controls={ views.map( ( view ) => ( {
|
||||
...view,
|
||||
title: view.label,
|
||||
onClick: () => setCurrentView( view ),
|
||||
} ) ) }
|
||||
/>
|
||||
</Toolbar>
|
||||
</BlockControls>
|
||||
<Toolbar>
|
||||
<ToolbarDropdownMenu
|
||||
label={ __( 'Switch view', 'woo-gutenberg-products-block' ) }
|
||||
text={ currentView.label }
|
||||
icon={
|
||||
<Icon srcElement={ eye } style={ { marginRight: '8px' } } />
|
||||
}
|
||||
controls={ views.map( ( view ) => ( {
|
||||
...view,
|
||||
title: view.label,
|
||||
onClick: () => {
|
||||
setCurrentView( view );
|
||||
selectBlock(
|
||||
getBlock( clientId ).innerBlocks.find(
|
||||
( block: { name: string } ) =>
|
||||
block.name === view.view
|
||||
)?.clientId || clientId
|
||||
);
|
||||
},
|
||||
} ) ) }
|
||||
/>
|
||||
</Toolbar>
|
||||
);
|
||||
|
||||
return {
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue