Show the drawer contents.
This commit is contained in:
parent
a1f98466bb
commit
f930a2af5b
|
@ -41,7 +41,6 @@ interface Store {
|
||||||
initialize: () => void;
|
initialize: () => void;
|
||||||
toggleDrawerOpen: ( event: Event ) => void;
|
toggleDrawerOpen: ( event: Event ) => void;
|
||||||
loadScripts: () => Promise< void >;
|
loadScripts: () => Promise< void >;
|
||||||
renderMiniCart: () => Promise< void >;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,13 +105,12 @@ const renderContents = async () => {
|
||||||
'./render-mini-cart-contents'
|
'./render-mini-cart-contents'
|
||||||
);
|
);
|
||||||
|
|
||||||
const container = document.querySelector(
|
const container = document.querySelector< HTMLDivElement >(
|
||||||
'.wc-block-mini-cart-interactivity__template-part'
|
'.wc-block-mini-cart-interactivity__template-part'
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log( 'renderContents', container );
|
|
||||||
|
|
||||||
if ( container ) {
|
if ( container ) {
|
||||||
|
container.style.display = 'block';
|
||||||
renderMiniCartContents( container );
|
renderMiniCartContents( container );
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -212,12 +210,6 @@ store< Store >( 'woocommerce/mini-cart-interactivity', {
|
||||||
await loadScripts();
|
await loadScripts();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove adding to cart event handler.
|
|
||||||
document.body.removeEventListener(
|
|
||||||
'wc-blocks_adding_to_cart',
|
|
||||||
loadScripts
|
|
||||||
);
|
|
||||||
|
|
||||||
document.body.addEventListener(
|
document.body.addEventListener(
|
||||||
'wc-mini-cart-interactivity-close-drawer',
|
'wc-mini-cart-interactivity-close-drawer',
|
||||||
() => {
|
() => {
|
||||||
|
@ -225,6 +217,12 @@ store< Store >( 'woocommerce/mini-cart-interactivity', {
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Remove adding to cart event handler.
|
||||||
|
document.body.removeEventListener(
|
||||||
|
'wc-blocks_adding_to_cart',
|
||||||
|
loadScripts
|
||||||
|
);
|
||||||
|
|
||||||
removeJQueryAddedToCartEvent();
|
removeJQueryAddedToCartEvent();
|
||||||
removeJQueryRemovedFromCartEvent();
|
removeJQueryRemovedFromCartEvent();
|
||||||
removeJQueryAddingToCartEvent();
|
removeJQueryAddingToCartEvent();
|
||||||
|
|
|
@ -1,244 +0,0 @@
|
||||||
/**
|
|
||||||
* External dependencies
|
|
||||||
*/
|
|
||||||
import { renderParentBlock } from '@woocommerce/atomic-utils';
|
|
||||||
import Drawer from '@woocommerce/base-components/drawer';
|
|
||||||
import { useStoreCart } from '@woocommerce/base-context/hooks';
|
|
||||||
import {
|
|
||||||
getValidBlockAttributes,
|
|
||||||
translateJQueryEventToNative,
|
|
||||||
} from '@woocommerce/base-utils';
|
|
||||||
import { getRegisteredBlockComponents } from '@woocommerce/blocks-registry';
|
|
||||||
import { isCartResponseTotals, isNumber } from '@woocommerce/types';
|
|
||||||
import { useCallback, useEffect, useRef, useState } from '@wordpress/element';
|
|
||||||
import clsx from 'clsx';
|
|
||||||
import type { ReactRootWithContainer } from '@woocommerce/base-utils';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal dependencies
|
|
||||||
*/
|
|
||||||
import type { BlockAttributes } from '../mini-cart/types';
|
|
||||||
import { MiniCartContentsBlock } from '../mini-cart/mini-cart-contents/block';
|
|
||||||
import './style.scss';
|
|
||||||
import {
|
|
||||||
blockName,
|
|
||||||
attributes as miniCartContentsAttributes,
|
|
||||||
} from '../mini-cart/mini-cart-contents/attributes';
|
|
||||||
|
|
||||||
type Props = BlockAttributes & { onClose: () => void };
|
|
||||||
|
|
||||||
function getScrollbarWidth() {
|
|
||||||
return window.innerWidth - document.documentElement.clientWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const MiniCartDrawer = ( attributes: Props ): JSX.Element => {
|
|
||||||
const {
|
|
||||||
isInitiallyOpen = false,
|
|
||||||
contents = '',
|
|
||||||
addToCartBehaviour = 'none',
|
|
||||||
onClose,
|
|
||||||
} = attributes;
|
|
||||||
|
|
||||||
const {
|
|
||||||
cartItemsCount: cartItemsCountFromApi,
|
|
||||||
cartIsLoading,
|
|
||||||
cartTotals: cartTotalsFromApi,
|
|
||||||
} = useStoreCart();
|
|
||||||
|
|
||||||
const cartIsLoadingForTheFirstTime = useRef( cartIsLoading );
|
|
||||||
|
|
||||||
useEffect( () => {
|
|
||||||
if ( cartIsLoadingForTheFirstTime.current && ! cartIsLoading ) {
|
|
||||||
cartIsLoadingForTheFirstTime.current = false;
|
|
||||||
}
|
|
||||||
}, [ cartIsLoading, cartIsLoadingForTheFirstTime ] );
|
|
||||||
|
|
||||||
useEffect( () => {
|
|
||||||
if (
|
|
||||||
! cartIsLoading &&
|
|
||||||
isCartResponseTotals( cartTotalsFromApi ) &&
|
|
||||||
isNumber( cartItemsCountFromApi )
|
|
||||||
) {
|
|
||||||
// Save server data to local storage, so we can re-fetch it faster
|
|
||||||
// on the next page load.
|
|
||||||
localStorage.setItem(
|
|
||||||
'wc-blocks_mini_cart_totals',
|
|
||||||
JSON.stringify( {
|
|
||||||
totals: cartTotalsFromApi,
|
|
||||||
itemsCount: cartItemsCountFromApi,
|
|
||||||
} )
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
const [ isOpen, setIsOpen ] = useState< boolean >( isInitiallyOpen );
|
|
||||||
// We already rendered the HTML drawer placeholder, so we want to skip the
|
|
||||||
// slide in animation.
|
|
||||||
const [ skipSlideIn, setSkipSlideIn ] =
|
|
||||||
useState< boolean >( isInitiallyOpen );
|
|
||||||
const [ contentsNode, setContentsNode ] = useState< HTMLDivElement | null >(
|
|
||||||
null
|
|
||||||
);
|
|
||||||
|
|
||||||
// Hack to force re-render when elements are not rendered in expected order.
|
|
||||||
const [ observerState, setObserverState ] = useState< boolean >( false );
|
|
||||||
|
|
||||||
const contentsRef = useCallback(
|
|
||||||
( node ) => {
|
|
||||||
setContentsNode( node );
|
|
||||||
|
|
||||||
if ( node ) {
|
|
||||||
const mutationObserver = new MutationObserver(
|
|
||||||
( mutationsList ) => {
|
|
||||||
for ( const mutation of mutationsList ) {
|
|
||||||
if ( mutation.type === 'childList' ) {
|
|
||||||
// Check if a child matching the selector exists
|
|
||||||
const childElement = node.querySelector(
|
|
||||||
'.wc-block-components-drawer__close-wrapper'
|
|
||||||
);
|
|
||||||
if ( childElement ) {
|
|
||||||
// Hack to force re-render when elements are not rendered in expected order.
|
|
||||||
setObserverState( ! observerState );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
mutationObserver.observe( node, {
|
|
||||||
childList: true,
|
|
||||||
subtree: true,
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[ observerState ]
|
|
||||||
);
|
|
||||||
|
|
||||||
const rootRef = useRef< ReactRootWithContainer[] | null >( null );
|
|
||||||
|
|
||||||
useEffect( () => {
|
|
||||||
const body = document.querySelector( 'body' );
|
|
||||||
if ( body ) {
|
|
||||||
const scrollBarWidth = getScrollbarWidth();
|
|
||||||
if ( isOpen ) {
|
|
||||||
Object.assign( body.style, {
|
|
||||||
overflow: 'hidden',
|
|
||||||
paddingRight: scrollBarWidth + 'px',
|
|
||||||
} );
|
|
||||||
} else {
|
|
||||||
Object.assign( body.style, { overflow: '', paddingRight: 0 } );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, [ isOpen ] );
|
|
||||||
|
|
||||||
useEffect( () => {
|
|
||||||
if ( contentsNode instanceof Element ) {
|
|
||||||
const container = contentsNode.querySelector(
|
|
||||||
'.wp-block-woocommerce-mini-cart-contents'
|
|
||||||
);
|
|
||||||
if ( ! container ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if ( isOpen ) {
|
|
||||||
const renderedBlock = renderParentBlock( {
|
|
||||||
Block: MiniCartContentsBlock,
|
|
||||||
blockName,
|
|
||||||
getProps: ( el: Element ) => {
|
|
||||||
return {
|
|
||||||
attributes: getValidBlockAttributes(
|
|
||||||
miniCartContentsAttributes,
|
|
||||||
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
||||||
( el instanceof HTMLElement
|
|
||||||
? el.dataset
|
|
||||||
: {} ) as any
|
|
||||||
),
|
|
||||||
};
|
|
||||||
},
|
|
||||||
selector: '.wp-block-woocommerce-mini-cart-contents',
|
|
||||||
blockMap: getRegisteredBlockComponents( blockName ),
|
|
||||||
} );
|
|
||||||
rootRef.current = renderedBlock;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
if ( contentsNode instanceof Element && isOpen ) {
|
|
||||||
const unmountingContainer = contentsNode?.querySelector(
|
|
||||||
'.wp-block-woocommerce-mini-cart-contents'
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( unmountingContainer ) {
|
|
||||||
const foundRoot = rootRef?.current?.find(
|
|
||||||
( { container } ) => unmountingContainer === container
|
|
||||||
);
|
|
||||||
if ( typeof foundRoot?.root?.unmount === 'function' ) {
|
|
||||||
setTimeout( () => {
|
|
||||||
foundRoot.root.unmount();
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [ isOpen, contentsNode ] );
|
|
||||||
|
|
||||||
useEffect( () => {
|
|
||||||
const openDrawer = () => {
|
|
||||||
setSkipSlideIn( false );
|
|
||||||
setIsOpen( true );
|
|
||||||
};
|
|
||||||
|
|
||||||
const openMiniCart = () => {
|
|
||||||
if ( addToCartBehaviour === 'open_drawer' ) {
|
|
||||||
openDrawer();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
document.body.addEventListener(
|
|
||||||
'wc-mini-cart-interactivity-open-drawer',
|
|
||||||
openDrawer
|
|
||||||
);
|
|
||||||
|
|
||||||
// Make it so we can read jQuery events triggered by WC Core elements.
|
|
||||||
const removeJQueryAddedToCartEvent = translateJQueryEventToNative(
|
|
||||||
'added_to_cart',
|
|
||||||
'wc-blocks_added_to_cart'
|
|
||||||
);
|
|
||||||
|
|
||||||
document.body.addEventListener(
|
|
||||||
'wc-blocks_added_to_cart',
|
|
||||||
openMiniCart
|
|
||||||
);
|
|
||||||
|
|
||||||
return () => {
|
|
||||||
removeJQueryAddedToCartEvent();
|
|
||||||
|
|
||||||
document.body.removeEventListener(
|
|
||||||
'wc-blocks_added_to_cart',
|
|
||||||
openMiniCart
|
|
||||||
);
|
|
||||||
};
|
|
||||||
}, [ addToCartBehaviour ] );
|
|
||||||
|
|
||||||
return (
|
|
||||||
// We only render the drawer in this component now. The button is controlled by Interactivity API.
|
|
||||||
<>
|
|
||||||
<Drawer
|
|
||||||
className={ clsx( 'wc-block-mini-cart__drawer', 'is-mobile', {
|
|
||||||
'is-loading': cartIsLoading,
|
|
||||||
} ) }
|
|
||||||
isOpen={ isOpen }
|
|
||||||
onClose={ () => {
|
|
||||||
onClose();
|
|
||||||
setIsOpen( false );
|
|
||||||
} }
|
|
||||||
slideIn={ ! skipSlideIn }
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
className="wc-block-mini-cart-interactivity__template-part"
|
|
||||||
ref={ contentsRef }
|
|
||||||
dangerouslySetInnerHTML={ { __html: contents } }
|
|
||||||
></div>
|
|
||||||
</Drawer>
|
|
||||||
</>
|
|
||||||
);
|
|
||||||
};
|
|
Loading…
Reference in New Issue