Clone the template to render the contents on every drawer open
This commit is contained in:
parent
f930a2af5b
commit
fadebe8302
|
@ -8,6 +8,7 @@ import lazyLoadScript, {
|
|||
isScriptTagInDOM,
|
||||
} from '@woocommerce/base-utils/lazy-load-script';
|
||||
import {
|
||||
ReactRootWithContainer,
|
||||
getNavigationType,
|
||||
translateJQueryEventToNative,
|
||||
} from '@woocommerce/base-utils';
|
||||
|
@ -32,15 +33,19 @@ interface dependencyData {
|
|||
translations?: string;
|
||||
}
|
||||
|
||||
interface State {
|
||||
root: ReactRootWithContainer[] | undefined;
|
||||
displayQuantityBadgeStyle: string;
|
||||
priceAriaLabel: string;
|
||||
}
|
||||
|
||||
interface Store {
|
||||
state: {
|
||||
displayQuantityBadgeStyle: string;
|
||||
priceAriaLabel: string;
|
||||
};
|
||||
state: State;
|
||||
callbacks: {
|
||||
initialize: () => void;
|
||||
toggleDrawerOpen: ( event: Event ) => void;
|
||||
loadScripts: () => Promise< void >;
|
||||
closeDrawer: () => void;
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -100,23 +105,23 @@ const loadScripts = async () => {
|
|||
}
|
||||
};
|
||||
|
||||
const renderContents = async () => {
|
||||
const renderContents = async ( state: State ) => {
|
||||
const { renderMiniCartContents } = await import(
|
||||
'./render-mini-cart-contents'
|
||||
);
|
||||
|
||||
const container = document.querySelector< HTMLDivElement >(
|
||||
const templateContainer = document.querySelector< HTMLDivElement >(
|
||||
'.wc-block-mini-cart-interactivity__template-part'
|
||||
);
|
||||
|
||||
if ( container ) {
|
||||
container.style.display = 'block';
|
||||
renderMiniCartContents( container );
|
||||
if ( templateContainer ) {
|
||||
state.root = renderMiniCartContents( templateContainer );
|
||||
}
|
||||
};
|
||||
|
||||
store< Store >( 'woocommerce/mini-cart-interactivity', {
|
||||
const { state } = store< Store >( 'woocommerce/mini-cart-interactivity', {
|
||||
state: {
|
||||
root: undefined,
|
||||
get displayQuantityBadgeStyle() {
|
||||
const context = getContext< Context >();
|
||||
return context.cartItemCount > 0 ? 'flex' : 'none';
|
||||
|
@ -198,10 +203,21 @@ store< Store >( 'woocommerce/mini-cart-interactivity', {
|
|||
context.drawerOpen = ! context.drawerOpen;
|
||||
|
||||
if ( context.drawerOpen ) {
|
||||
await renderContents();
|
||||
if ( state.root ) {
|
||||
state.root.forEach( ( root ) => {
|
||||
root.root.unmount();
|
||||
} );
|
||||
}
|
||||
|
||||
await renderContents( state );
|
||||
}
|
||||
},
|
||||
|
||||
closeDrawer: () => {
|
||||
const context = getContext< Context >();
|
||||
context.drawerOpen = false;
|
||||
},
|
||||
|
||||
loadScripts: async () => {
|
||||
const context = getContext< Context >();
|
||||
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { CartEventsProvider } from '@woocommerce/base-context';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import '../../mini-cart/mini-cart-contents/inner-blocks/register-components';
|
||||
|
||||
type MiniCartContentsBlockProps = {
|
||||
attributes: Record< string, unknown >;
|
||||
children: JSX.Element | JSX.Element[];
|
||||
};
|
||||
|
||||
export const MiniCartContentsBlock = (
|
||||
props: MiniCartContentsBlockProps
|
||||
): JSX.Element => {
|
||||
const { children } = props;
|
||||
|
||||
console.log( 'MiniCartContentsBlock', children );
|
||||
|
||||
return <CartEventsProvider>{ children }</CartEventsProvider>;
|
||||
};
|
|
@ -7,22 +7,32 @@ import { getRegisteredBlockComponents } from '@woocommerce/blocks-registry';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { renderParentBlock } from '../../atomic/utils';
|
||||
import { MiniCartContentsBlock } from '../mini-cart/mini-cart-contents/block';
|
||||
import { MiniCartContentsBlock } from './mini-cart-contents/block';
|
||||
import { attributes as miniCartContentsAttributes } from '../mini-cart/mini-cart-contents/attributes';
|
||||
import { getValidBlockAttributes } from '../../base/utils';
|
||||
import '../mini-cart/mini-cart-contents/inner-blocks/register-components';
|
||||
|
||||
const generateUniqueId = () => {
|
||||
return (
|
||||
Date.now().toString() + Math.floor( Math.random() * 10000 ).toString()
|
||||
);
|
||||
};
|
||||
|
||||
// We load this async so that we don't have to load the mini-cart block.
|
||||
export const renderMiniCartContents = ( contentsNode: Element ) => {
|
||||
const container = contentsNode.querySelector(
|
||||
'.wp-block-woocommerce-mini-cart-contents'
|
||||
export const renderMiniCartContents = ( templateElement: HTMLDivElement ) => {
|
||||
const clonedTemplateNode = templateElement.cloneNode(
|
||||
true
|
||||
) as HTMLDivElement;
|
||||
|
||||
const uniqueId = `mini-cart-template-${ generateUniqueId() }`;
|
||||
( clonedTemplateNode as HTMLElement ).id = uniqueId;
|
||||
|
||||
templateElement.insertAdjacentElement(
|
||||
'afterend',
|
||||
clonedTemplateNode as HTMLDivElement
|
||||
);
|
||||
|
||||
if ( ! container ) {
|
||||
return;
|
||||
}
|
||||
|
||||
renderParentBlock( {
|
||||
const root = renderParentBlock( {
|
||||
Block: MiniCartContentsBlock,
|
||||
blockName: 'woocommerce/mini-cart-contents',
|
||||
getProps: ( el: Element ) => {
|
||||
|
@ -34,9 +44,14 @@ export const renderMiniCartContents = ( contentsNode: Element ) => {
|
|||
),
|
||||
};
|
||||
},
|
||||
selector: '.wp-block-woocommerce-mini-cart-contents',
|
||||
// TODO we should get the template but not render into the same container.
|
||||
selector: `#${ uniqueId } .wp-block-woocommerce-mini-cart-contents`,
|
||||
blockMap: getRegisteredBlockComponents(
|
||||
'woocommerce/mini-cart-contents'
|
||||
),
|
||||
} );
|
||||
|
||||
clonedTemplateNode.style.display = 'block';
|
||||
|
||||
return root;
|
||||
};
|
|
@ -470,9 +470,9 @@ class MiniCartInteractivity extends AbstractBlock {
|
|||
protected function get_template_part_contents_container( $template_contents ) {
|
||||
ob_start();
|
||||
?>
|
||||
<div class="wc-block-mini-cart-interactivity__template-part" style="display:none">
|
||||
<?php echo wp_kses_post( $template_contents ); ?>
|
||||
</div>
|
||||
<div class="wc-block-mini-cart-interactivity__template-part" style="display:none">
|
||||
<?php echo wp_kses_post( $template_contents ); ?>
|
||||
</div>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
@ -508,6 +508,7 @@ class MiniCartInteractivity extends AbstractBlock {
|
|||
);
|
||||
|
||||
$interactivity_namespace = wp_json_encode( array( 'namespace' => $this->get_full_block_name() ), JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP );
|
||||
$close_button = Drawer::render_close_button( 'woocommerce/mini-cart-interactivity::callbacks.closeDrawer' );
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
|
@ -522,7 +523,7 @@ class MiniCartInteractivity extends AbstractBlock {
|
|||
echo Drawer::render(
|
||||
array(
|
||||
'is_initially_open' => false,
|
||||
'children' => $this->get_template_part_contents_container( $template_part_contents ),
|
||||
'children' => $close_button . $this->get_template_part_contents_container( $template_part_contents ),
|
||||
// TODO - clean up this concept.
|
||||
'is_open_context_property' => 'woocommerce/mini-cart-interactivity::context.drawerOpen',
|
||||
'on_open' => 'woocommerce/mini-cart-interactivity::actions.renderMiniCart',
|
||||
|
|
|
@ -27,14 +27,15 @@ class Drawer {
|
|||
'isOpenContextProperty' => $props['is_open_context_property'] ?? 'woocommerce/interactivity-drawer',
|
||||
);
|
||||
|
||||
$button_aria_label = __( 'Close', 'woocommerce' );
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
|
||||
<div data-wc-body data-wc-init="actions.initialize" data-wc-interactive="<?php echo esc_attr( $namespace ); ?>" data-wc-context="<?php echo esc_attr( wp_json_encode( $context ) ); ?>" >
|
||||
<div tab-index="0" data-wc-bind--class="state.slideClasses" class="wc-block-components-drawer__screen-overlay wc-block-components-drawer__screen-overlay--is-hidden" >
|
||||
<div class="wc-block-components-drawer" role="dialog" tab-index="-1">
|
||||
<div class="wc-block-components-drawer__content" role="document">
|
||||
<!-- TODO: CloseButtonPortal -->
|
||||
<div class="wc-block-components-drawer__content" role="document">
|
||||
<?php echo $props['children']; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -43,4 +44,23 @@ class Drawer {
|
|||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Render the close button. Allows you to customize where it's rendered.
|
||||
*
|
||||
* @param string $on_close_action The action to perform when the close button is clicked.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function render_close_button( $on_close_action ) {
|
||||
ob_start();
|
||||
?>
|
||||
<div class="wc-block-components-drawer__close-wrapper">
|
||||
<button data-wc-on--click="<?php echo esc_attr( $on_close_action ); ?>" class="wc-block-components-button wp-element-button wc-block-components-drawer__close contained" aria-label="Close" type="button">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="24" height="24" aria-hidden="true" focusable="false"><path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path></svg>
|
||||
</button>
|
||||
</div>
|
||||
<?php
|
||||
return ob_get_clean();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue