Checkout: Collapsible Order Summary in mobile view (#52253)
This commit is contained in:
parent
f5d5caa3f0
commit
601e14a253
|
@ -54,6 +54,7 @@
|
|||
"@wordpress/data",
|
||||
"@wordpress/data-controls",
|
||||
"@wordpress/date",
|
||||
"@wordpress/editor",
|
||||
"@wordpress/dependency-extraction-webpack-plugin",
|
||||
"@wordpress/deprecated",
|
||||
"@wordpress/dom",
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useContainerWidthContext } from '@woocommerce/base-context';
|
||||
import { Panel } from '@woocommerce/blocks-components';
|
||||
import type { CartItem } from '@woocommerce/types';
|
||||
import clsx from 'clsx';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -26,15 +25,10 @@ const OrderSummary = ( {
|
|||
}
|
||||
|
||||
return (
|
||||
<Panel
|
||||
className="wc-block-components-order-summary"
|
||||
initialOpen={ isLarge }
|
||||
hasBorder={ false }
|
||||
title={
|
||||
<span className="wc-block-components-order-summary__button-text">
|
||||
{ __( 'Order summary', 'woocommerce' ) }
|
||||
</span>
|
||||
}
|
||||
<div
|
||||
className={ clsx( 'wc-block-components-order-summary', {
|
||||
'is-large': isLarge,
|
||||
} ) }
|
||||
>
|
||||
<div className="wc-block-components-order-summary__content">
|
||||
{ cartItems.map( ( cartItem ) => {
|
||||
|
@ -46,7 +40,7 @@ const OrderSummary = ( {
|
|||
);
|
||||
} ) }
|
||||
</div>
|
||||
</Panel>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
.wc-block-components-order-summary {
|
||||
// Compensate for removing Panel.
|
||||
padding: 0 $gap;
|
||||
|
||||
.wc-block-components-order-summary__button-text {
|
||||
font-weight: 500;
|
||||
}
|
||||
|
|
|
@ -16,6 +16,10 @@
|
|||
gap: $gap-smaller;
|
||||
flex-wrap: wrap;
|
||||
|
||||
.wc-block-components-text-input.wc-block-components-totals-coupon__input {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.wc-block-components-totals-coupon__input,
|
||||
.wc-block-components-totals-coupon__button {
|
||||
margin: 0;
|
||||
|
|
|
@ -20,8 +20,11 @@ import { previewCart } from '@woocommerce/resource-previews';
|
|||
*/
|
||||
import { useStoreEvents } from '../use-store-events';
|
||||
import type { ShippingData } from './types';
|
||||
import { useEditorContext } from '../../providers';
|
||||
|
||||
export const useShippingData = (): ShippingData => {
|
||||
const { isEditor } = useEditorContext();
|
||||
|
||||
const {
|
||||
shippingRates,
|
||||
needsShipping,
|
||||
|
@ -29,32 +32,37 @@ export const useShippingData = (): ShippingData => {
|
|||
isLoadingRates,
|
||||
isCollectable,
|
||||
isSelectingRate,
|
||||
} = useSelect( ( select ) => {
|
||||
const isEditor = !! select( 'core/editor' );
|
||||
const store = select( storeKey );
|
||||
const rates = isEditor
|
||||
? previewCart.shipping_rates
|
||||
: store.getShippingRates();
|
||||
return {
|
||||
shippingRates: rates,
|
||||
needsShipping: isEditor
|
||||
? previewCart.needs_shipping
|
||||
: store.getNeedsShipping(),
|
||||
hasCalculatedShipping: isEditor
|
||||
? previewCart.has_calculated_shipping
|
||||
: store.getHasCalculatedShipping(),
|
||||
isLoadingRates: isEditor ? false : store.isCustomerDataUpdating(),
|
||||
isCollectable: rates.every(
|
||||
( { shipping_rates: packageShippingRates } ) =>
|
||||
packageShippingRates.find( ( { method_id: methodId } ) =>
|
||||
hasCollectableRate( methodId )
|
||||
)
|
||||
),
|
||||
isSelectingRate: isEditor
|
||||
? false
|
||||
: store.isShippingRateBeingSelected(),
|
||||
};
|
||||
} );
|
||||
} = useSelect(
|
||||
( select ) => {
|
||||
const store = select( storeKey );
|
||||
const rates = isEditor
|
||||
? previewCart.shipping_rates
|
||||
: store.getShippingRates();
|
||||
return {
|
||||
shippingRates: rates,
|
||||
needsShipping: isEditor
|
||||
? previewCart.needs_shipping
|
||||
: store.getNeedsShipping(),
|
||||
hasCalculatedShipping: isEditor
|
||||
? previewCart.has_calculated_shipping
|
||||
: store.getHasCalculatedShipping(),
|
||||
isLoadingRates: isEditor
|
||||
? false
|
||||
: store.isCustomerDataUpdating(),
|
||||
isCollectable: rates.every(
|
||||
( { shipping_rates: packageShippingRates } ) =>
|
||||
packageShippingRates.find(
|
||||
( { method_id: methodId } ) =>
|
||||
hasCollectableRate( methodId )
|
||||
)
|
||||
),
|
||||
isSelectingRate: isEditor
|
||||
? false
|
||||
: store.isShippingRateBeingSelected(),
|
||||
};
|
||||
},
|
||||
[ isEditor ]
|
||||
);
|
||||
|
||||
// set selected rates on ref so it's always current.
|
||||
const selectedRates = useRef< Record< string, string > >( {} );
|
||||
|
|
|
@ -62,6 +62,7 @@
|
|||
}
|
||||
|
||||
.wc-block-components-address-form__address_2-toggle {
|
||||
display: inline-block;
|
||||
background: none;
|
||||
border: none;
|
||||
color: inherit;
|
||||
|
|
|
@ -7,6 +7,13 @@ import { innerBlockAreas } from '@woocommerce/blocks-checkout';
|
|||
import { TotalsFooterItem } from '@woocommerce/base-components/cart-checkout';
|
||||
import { getCurrencyFromPriceResponse } from '@woocommerce/price-format';
|
||||
import { useStoreCart } from '@woocommerce/base-context/hooks';
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { useId, useState } from '@wordpress/element';
|
||||
import { Icon } from '@wordpress/components';
|
||||
import { chevronDown, chevronUp } from '@wordpress/icons';
|
||||
import clsx from 'clsx';
|
||||
import { FormattedMonetaryAmount } from '@woocommerce/blocks-components';
|
||||
import { useContainerWidthContext } from '@woocommerce/base-context';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
|
@ -21,9 +28,29 @@ export const Edit = ( { clientId }: { clientId: string } ): JSX.Element => {
|
|||
const blockProps = useBlockProps();
|
||||
const { cartTotals } = useStoreCart();
|
||||
const totalsCurrency = getCurrencyFromPriceResponse( cartTotals );
|
||||
const totalPrice = parseInt( cartTotals.total_price, 10 );
|
||||
const allowedBlocks = getAllowedBlocks(
|
||||
innerBlockAreas.CHECKOUT_ORDER_SUMMARY
|
||||
);
|
||||
const { isLarge } = useContainerWidthContext();
|
||||
const [ isOpen, setIsOpen ] = useState( false );
|
||||
const ariaControlsId = useId();
|
||||
|
||||
const orderSummaryProps = ! isLarge
|
||||
? {
|
||||
role: 'button',
|
||||
onClick: () => setIsOpen( ! isOpen ),
|
||||
'aria-expanded': isOpen,
|
||||
'aria-controls': ariaControlsId,
|
||||
tabIndex: 0,
|
||||
onKeyDown: ( event: React.KeyboardEvent ) => {
|
||||
if ( event.key === 'Enter' || event.key === ' ' ) {
|
||||
setIsOpen( ! isOpen );
|
||||
}
|
||||
},
|
||||
}
|
||||
: {};
|
||||
|
||||
const defaultTemplate = [
|
||||
[ 'woocommerce/checkout-order-summary-cart-items-block', {}, [] ],
|
||||
[ 'woocommerce/checkout-order-summary-coupon-form-block', {}, [] ],
|
||||
|
@ -38,17 +65,48 @@ export const Edit = ( { clientId }: { clientId: string } ): JSX.Element => {
|
|||
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<InnerBlocks
|
||||
allowedBlocks={ allowedBlocks }
|
||||
template={ defaultTemplate }
|
||||
/>
|
||||
<div className="wc-block-components-totals-wrapper">
|
||||
<TotalsFooterItem
|
||||
currency={ totalsCurrency }
|
||||
values={ cartTotals }
|
||||
/>
|
||||
<div
|
||||
className="wc-block-components-checkout-order-summary__title"
|
||||
{ ...orderSummaryProps }
|
||||
>
|
||||
<p
|
||||
className="wc-block-components-checkout-order-summary__title-text"
|
||||
role="heading"
|
||||
>
|
||||
{ __( 'Order summary', 'woocommerce' ) }
|
||||
</p>
|
||||
{ ! isLarge && (
|
||||
<>
|
||||
<FormattedMonetaryAmount
|
||||
currency={ totalsCurrency }
|
||||
value={ totalPrice }
|
||||
/>
|
||||
|
||||
<Icon icon={ isOpen ? chevronUp : chevronDown } />
|
||||
</>
|
||||
) }
|
||||
</div>
|
||||
<div
|
||||
className={ clsx(
|
||||
'wc-block-components-checkout-order-summary__content',
|
||||
{
|
||||
'is-open': isOpen,
|
||||
}
|
||||
) }
|
||||
id={ ariaControlsId }
|
||||
>
|
||||
<InnerBlocks
|
||||
allowedBlocks={ allowedBlocks }
|
||||
template={ defaultTemplate }
|
||||
/>
|
||||
<div className="wc-block-components-totals-wrapper">
|
||||
<TotalsFooterItem
|
||||
currency={ totalsCurrency }
|
||||
values={ cartTotals }
|
||||
/>
|
||||
</div>
|
||||
<OrderMetaSlotFill />
|
||||
</div>
|
||||
<OrderMetaSlotFill />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -4,11 +4,17 @@
|
|||
import { TotalsFooterItem } from '@woocommerce/base-components/cart-checkout';
|
||||
import { getCurrencyFromPriceResponse } from '@woocommerce/price-format';
|
||||
import { useStoreCart } from '@woocommerce/base-context/hooks';
|
||||
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import { Icon, chevronDown, chevronUp } from '@wordpress/icons';
|
||||
import { useId, useState } from '@wordpress/element';
|
||||
import clsx from 'clsx';
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { OrderMetaSlotFill } from './slotfills';
|
||||
import { OrderMetaSlotFill, CheckoutOrderSummaryFill } from './slotfills';
|
||||
import { useContainerWidthContext } from '../../../../base/context';
|
||||
import { FormattedMonetaryAmount } from '../../../../../../packages/components';
|
||||
import { FormStepHeading } from '../../form-step';
|
||||
|
||||
const FrontendBlock = ( {
|
||||
children,
|
||||
|
@ -18,19 +24,104 @@ const FrontendBlock = ( {
|
|||
className?: string;
|
||||
} ): JSX.Element | null => {
|
||||
const { cartTotals } = useStoreCart();
|
||||
const totalsCurrency = getCurrencyFromPriceResponse( cartTotals );
|
||||
const { isLarge } = useContainerWidthContext();
|
||||
const [ isOpen, setIsOpen ] = useState( false );
|
||||
|
||||
const totalsCurrency = getCurrencyFromPriceResponse( cartTotals );
|
||||
const totalPrice = parseInt( cartTotals.total_price, 10 );
|
||||
const ariaControlsId = useId();
|
||||
|
||||
const orderSummaryProps = ! isLarge
|
||||
? {
|
||||
role: 'button',
|
||||
onClick: () => setIsOpen( ! isOpen ),
|
||||
'aria-expanded': isOpen,
|
||||
'aria-controls': ariaControlsId,
|
||||
tabIndex: 0,
|
||||
onKeyDown: ( event: React.KeyboardEvent ) => {
|
||||
if ( event.key === 'Enter' || event.key === ' ' ) {
|
||||
setIsOpen( ! isOpen );
|
||||
}
|
||||
},
|
||||
}
|
||||
: {};
|
||||
|
||||
// Render the summary once here in the block and once in the fill. The fill can be slotted once elsewhere. The fill is only
|
||||
// rendered on small and mobile screens.
|
||||
return (
|
||||
<div className={ className }>
|
||||
{ children }
|
||||
<div className="wc-block-components-totals-wrapper">
|
||||
<TotalsFooterItem
|
||||
currency={ totalsCurrency }
|
||||
values={ cartTotals }
|
||||
/>
|
||||
<>
|
||||
<div className={ className }>
|
||||
<div
|
||||
className={ clsx(
|
||||
'wc-block-components-checkout-order-summary__title',
|
||||
{
|
||||
'is-open': isOpen,
|
||||
}
|
||||
) }
|
||||
{ ...orderSummaryProps }
|
||||
>
|
||||
<p
|
||||
className="wc-block-components-checkout-order-summary__title-text"
|
||||
role="heading"
|
||||
>
|
||||
{ __( 'Order summary', 'woocommerce' ) }
|
||||
</p>
|
||||
{ ! isLarge && (
|
||||
<>
|
||||
<FormattedMonetaryAmount
|
||||
currency={ totalsCurrency }
|
||||
value={ totalPrice }
|
||||
/>
|
||||
|
||||
<Icon
|
||||
className="wc-block-components-checkout-order-summary__title-icon"
|
||||
icon={ isOpen ? chevronUp : chevronDown }
|
||||
/>
|
||||
</>
|
||||
) }
|
||||
</div>
|
||||
<div
|
||||
className={ clsx(
|
||||
'wc-block-components-checkout-order-summary__content',
|
||||
{
|
||||
'is-open': isOpen,
|
||||
}
|
||||
) }
|
||||
id={ ariaControlsId }
|
||||
>
|
||||
{ children }
|
||||
<div className="wc-block-components-totals-wrapper">
|
||||
<TotalsFooterItem
|
||||
currency={ totalsCurrency }
|
||||
values={ cartTotals }
|
||||
/>
|
||||
</div>
|
||||
<OrderMetaSlotFill />
|
||||
</div>
|
||||
</div>
|
||||
<OrderMetaSlotFill />
|
||||
</div>
|
||||
|
||||
{ ! isLarge && (
|
||||
<CheckoutOrderSummaryFill>
|
||||
<div
|
||||
className={ `${ className } checkout-order-summary-block-fill-wrapper` }
|
||||
>
|
||||
<FormStepHeading>
|
||||
<>{ __( 'Order summary', 'woocommerce' ) }</>
|
||||
</FormStepHeading>
|
||||
<div className="checkout-order-summary-block-fill">
|
||||
{ children }
|
||||
<div className="wc-block-components-totals-wrapper">
|
||||
<TotalsFooterItem
|
||||
currency={ totalsCurrency }
|
||||
values={ cartTotals }
|
||||
/>
|
||||
</div>
|
||||
<OrderMetaSlotFill />
|
||||
</div>
|
||||
</div>
|
||||
</CheckoutOrderSummaryFill>
|
||||
) }
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -11,6 +11,7 @@ import { registerBlockType } from '@wordpress/blocks';
|
|||
import { Edit, Save } from './edit';
|
||||
import attributes from './attributes';
|
||||
import deprecated from './deprecated';
|
||||
import './style.scss';
|
||||
|
||||
registerBlockType( 'woocommerce/checkout-order-summary-block', {
|
||||
icon: {
|
||||
|
|
|
@ -1,7 +1,10 @@
|
|||
/**
|
||||
* External dependencies
|
||||
*/
|
||||
import { ExperimentalOrderMeta } from '@woocommerce/blocks-checkout';
|
||||
import {
|
||||
ExperimentalOrderMeta,
|
||||
createSlotFill,
|
||||
} from '@woocommerce/blocks-checkout';
|
||||
import { useStoreCart } from '@woocommerce/base-context/hooks';
|
||||
|
||||
// @todo Consider deprecating OrderMetaSlotFill and DiscountSlotFill in favour of inner block areas.
|
||||
|
@ -17,3 +20,10 @@ export const OrderMetaSlotFill = (): JSX.Element => {
|
|||
|
||||
return <ExperimentalOrderMeta.Slot { ...slotFillProps } />;
|
||||
};
|
||||
|
||||
const checkoutOrderSummarySlotName = 'checkoutOrderSummaryActionArea';
|
||||
|
||||
export const {
|
||||
Fill: CheckoutOrderSummaryFill,
|
||||
Slot: CheckoutOrderSummarySlot,
|
||||
} = createSlotFill( checkoutOrderSummarySlotName );
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
.wp-block-woocommerce-checkout-order-summary-block {
|
||||
border: 1px solid $universal-border-light;
|
||||
border-radius: 5px;
|
||||
|
||||
.wc-block-components-formatted-money-amount {
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.wc-block-components-totals-wrapper:first-of-type {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-order-summary__title {
|
||||
margin-top: $gap;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
|
||||
.wc-block-components-checkout-order-summary__title-text {
|
||||
margin: 0 0 $gap $gap;
|
||||
flex-grow: 1;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-order-summary__title-open-close {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
.checkout-order-summary-block-fill {
|
||||
border: 1px solid $universal-border-light;
|
||||
border-radius: 5px;
|
||||
|
||||
.wc-block-components-totals-wrapper:first-of-type {
|
||||
border-top: 0;
|
||||
}
|
||||
|
||||
.wc-block-components-totals-item {
|
||||
padding-left: $gap;
|
||||
padding-right: $gap;
|
||||
}
|
||||
|
||||
.wc-block-components-totals-coupon {
|
||||
padding-left: $gap;
|
||||
padding-right: $gap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.has-dark-controls {
|
||||
.wp-block-woocommerce-checkout-order-summary-block {
|
||||
border: 1px solid $input-border-dark;
|
||||
}
|
||||
}
|
||||
|
||||
.is-small,
|
||||
.is-medium,
|
||||
.is-mobile {
|
||||
.wp-block-woocommerce-checkout-order-summary-block {
|
||||
margin-top: 0;
|
||||
border: none;
|
||||
|
||||
&.checkout-order-summary-block-fill-wrapper {
|
||||
padding-top: $gap-larger;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-order-summary__title {
|
||||
padding: 20px 0;
|
||||
cursor: pointer;
|
||||
border-top: 1px solid $universal-border-light;
|
||||
border-bottom: 1px solid $universal-border-light;
|
||||
|
||||
&.is-open {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-order-summary__title-text {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-order-summary__title-icon {
|
||||
fill: currentColor;
|
||||
}
|
||||
}
|
||||
|
||||
.wc-block-components-checkout-order-summary__content {
|
||||
display: none;
|
||||
|
||||
&.is-open {
|
||||
.wc-block-components-totals-wrapper:first-child {
|
||||
border-top: none;
|
||||
}
|
||||
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,7 @@ import { VALIDATION_STORE_KEY } from '@woocommerce/block-data';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import { termsConsentDefaultText, termsCheckboxDefaultText } from './constants';
|
||||
import { CheckoutOrderSummarySlot } from '../checkout-order-summary-block/slotfills';
|
||||
|
||||
const FrontendBlock = ( {
|
||||
text,
|
||||
|
@ -73,41 +74,47 @@ const FrontendBlock = ( {
|
|||
] );
|
||||
|
||||
return (
|
||||
<div
|
||||
className={ clsx(
|
||||
'wc-block-checkout__terms',
|
||||
{
|
||||
'wc-block-checkout__terms--disabled': isDisabled,
|
||||
'wc-block-checkout__terms--with-separator':
|
||||
showSeparator !== 'false' && showSeparator !== false,
|
||||
},
|
||||
className
|
||||
) }
|
||||
>
|
||||
{ checkbox ? (
|
||||
<>
|
||||
<CheckboxControl
|
||||
id="terms-and-conditions"
|
||||
checked={ checked }
|
||||
onChange={ () => setChecked( ( value ) => ! value ) }
|
||||
hasError={ hasError }
|
||||
disabled={ isDisabled }
|
||||
>
|
||||
<span
|
||||
dangerouslySetInnerHTML={ {
|
||||
__html: text || termsCheckboxDefaultText,
|
||||
} }
|
||||
/>
|
||||
</CheckboxControl>
|
||||
</>
|
||||
) : (
|
||||
<span
|
||||
dangerouslySetInnerHTML={ {
|
||||
__html: text || termsConsentDefaultText,
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
<>
|
||||
<CheckoutOrderSummarySlot />
|
||||
<div
|
||||
className={ clsx(
|
||||
'wc-block-checkout__terms',
|
||||
{
|
||||
'wc-block-checkout__terms--disabled': isDisabled,
|
||||
'wc-block-checkout__terms--with-separator':
|
||||
showSeparator !== 'false' &&
|
||||
showSeparator !== false,
|
||||
},
|
||||
className
|
||||
) }
|
||||
>
|
||||
{ checkbox ? (
|
||||
<>
|
||||
<CheckboxControl
|
||||
id="terms-and-conditions"
|
||||
checked={ checked }
|
||||
onChange={ () =>
|
||||
setChecked( ( value ) => ! value )
|
||||
}
|
||||
hasError={ hasError }
|
||||
disabled={ isDisabled }
|
||||
>
|
||||
<span
|
||||
dangerouslySetInnerHTML={ {
|
||||
__html: text || termsCheckboxDefaultText,
|
||||
} }
|
||||
/>
|
||||
</CheckboxControl>
|
||||
</>
|
||||
) : (
|
||||
<span
|
||||
dangerouslySetInnerHTML={ {
|
||||
__html: text || termsConsentDefaultText,
|
||||
} }
|
||||
/>
|
||||
) }
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
padding-top: $gap-largest;
|
||||
border-top: 1px solid $universal-border-light;
|
||||
|
||||
|
||||
.is-mobile &,
|
||||
.is-medium &,
|
||||
.is-small & {
|
||||
border-top: 0;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import clsx from 'clsx';
|
|||
import { Sidebar } from '@woocommerce/base-components/sidebar-layout';
|
||||
import { StoreNoticesContainer } from '@woocommerce/blocks-components';
|
||||
import { useObservedViewport } from '@woocommerce/base-hooks';
|
||||
import { useContainerWidthContext } from '@woocommerce/base-context';
|
||||
|
||||
const FrontendBlock = ( {
|
||||
children,
|
||||
className,
|
||||
|
@ -15,11 +17,14 @@ const FrontendBlock = ( {
|
|||
const [ observedRef, observedElement, viewWindow ] =
|
||||
useObservedViewport< HTMLDivElement >();
|
||||
const isSticky = observedElement.height < viewWindow.height;
|
||||
const { isLarge } = useContainerWidthContext();
|
||||
|
||||
return (
|
||||
<Sidebar
|
||||
ref={ observedRef }
|
||||
className={ clsx( 'wc-block-checkout__sidebar', className, {
|
||||
'is-sticky': isSticky,
|
||||
'is-large': isLarge,
|
||||
} ) }
|
||||
>
|
||||
<StoreNoticesContainer
|
||||
|
|
|
@ -27,23 +27,6 @@
|
|||
}
|
||||
}
|
||||
|
||||
.is-large {
|
||||
.wp-block-woocommerce-checkout-order-summary-block {
|
||||
border: 1px solid $universal-border-light;
|
||||
border-radius: 5px;
|
||||
|
||||
.wc-block-components-totals-wrapper:first-of-type {
|
||||
border-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
&.has-dark-controls {
|
||||
.wp-block-woocommerce-checkout-order-summary-block {
|
||||
border-color: $input-border-dark;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wp-block-woocommerce-checkout.is-loading {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
|
|
@ -170,6 +170,7 @@
|
|||
"@wordpress/data": "6.15.0",
|
||||
"@wordpress/data-controls": "2.2.7",
|
||||
"@wordpress/date": "4.44.0",
|
||||
"@wordpress/editor": "wp-6.7",
|
||||
"@wordpress/dependency-extraction-webpack-plugin": "4.28.0",
|
||||
"@wordpress/dom": "3.27.0",
|
||||
"@wordpress/dom-ready": "3.27.0",
|
||||
|
|
|
@ -23,11 +23,26 @@ import BlockErrorBoundary from '../components/error-boundary';
|
|||
* @param {Array} fills The list of fills to check for a valid one in.
|
||||
* @return {boolean} True if this slot contains any valid fills.
|
||||
*/
|
||||
export const hasValidFills = ( fills ) =>
|
||||
export const hasValidFills = ( fills: [] ) =>
|
||||
Array.isArray( fills ) && fills.filter( Boolean ).length > 0;
|
||||
|
||||
export { useSlot, useSlotFills };
|
||||
|
||||
type SlotFill = {
|
||||
Fill: (
|
||||
props: Partial< {
|
||||
bubblesVirtually: boolean;
|
||||
children: React.ReactNode;
|
||||
} >
|
||||
) => JSX.Element;
|
||||
Slot: (
|
||||
props: Partial< {
|
||||
bubblesVirtually: boolean;
|
||||
children: React.ReactNode;
|
||||
} >
|
||||
) => JSX.Element;
|
||||
};
|
||||
|
||||
/**
|
||||
* Abstracts @wordpress/components createSlotFill, wraps Fill in an error boundary and passes down fillProps.
|
||||
*
|
||||
|
@ -36,8 +51,10 @@ export { useSlot, useSlotFills };
|
|||
*
|
||||
* @return {Object} Returns a newly wrapped Fill and Slot.
|
||||
*/
|
||||
export const createSlotFill = ( slotName, onError = null ) => {
|
||||
const { Fill: BaseFill, Slot: BaseSlot } = baseCreateSlotFill( slotName );
|
||||
export const createSlotFill = ( slotName: string, onError = null ) => {
|
||||
const { Fill: BaseFill, Slot: BaseSlot } = baseCreateSlotFill(
|
||||
slotName
|
||||
) as SlotFill;
|
||||
|
||||
/**
|
||||
* A Fill that will get rendered inside associate slot.
|
||||
|
@ -47,9 +64,9 @@ export const createSlotFill = ( slotName, onError = null ) => {
|
|||
* @param {Object} props Items props.
|
||||
* @param {Array} props.children Children to be rendered.
|
||||
*/
|
||||
const Fill = ( { children } ) => (
|
||||
const Fill = ( { children }: { children: React.ReactNode } ) => (
|
||||
<BaseFill>
|
||||
{ ( fillProps ) =>
|
||||
{ ( fillProps: unknown ) =>
|
||||
Children.map( children, ( fill ) => (
|
||||
<BlockErrorBoundary
|
||||
/* Returning null would trigger the default error display.
|
||||
|
@ -59,6 +76,7 @@ export const createSlotFill = ( slotName, onError = null ) => {
|
|||
CURRENT_USER_IS_ADMIN ? onError : () => null
|
||||
}
|
||||
>
|
||||
{ /* @ts-expect-error It's not clear how to accurately type `fill`. */ }
|
||||
{ cloneElement( fill, fillProps ) }
|
||||
</BlockErrorBoundary>
|
||||
) )
|
||||
|
@ -76,7 +94,9 @@ export const createSlotFill = ( slotName, onError = null ) => {
|
|||
* @param {Element|string} props.as Element used to render the slot, defaults to div.
|
||||
*
|
||||
*/
|
||||
const Slot = ( props ) => <BaseSlot { ...props } bubblesVirtually />;
|
||||
const Slot = ( props: object ) => (
|
||||
<BaseSlot { ...props } bubblesVirtually />
|
||||
);
|
||||
|
||||
return {
|
||||
Fill,
|
|
@ -99,7 +99,7 @@ test.describe( 'Shopper → Translations', () => {
|
|||
).toBeVisible();
|
||||
|
||||
await expect(
|
||||
page.getByRole( 'button', {
|
||||
page.getByRole( 'heading', {
|
||||
name: 'Besteloverzicht',
|
||||
} )
|
||||
).toBeVisible();
|
||||
|
|
|
@ -1,3 +1,10 @@
|
|||
const { webcrypto } = require( 'node:crypto' );
|
||||
|
||||
global.crypto = webcrypto;
|
||||
|
||||
global.TextEncoder = require( 'util' ).TextEncoder;
|
||||
global.TextDecoder = require( 'util' ).TextDecoder;
|
||||
|
||||
// Set up `wp.*` aliases. Doing this because any tests importing wp stuff will likely run into this.
|
||||
global.wp = {};
|
||||
require( '@wordpress/data' );
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
Significance: minor
|
||||
Type: enhancement
|
||||
|
||||
Checkout: Add a collapsible order summary for smaller screens.
|
|
@ -786,10 +786,8 @@
|
|||
"node_modules/@woocommerce/e2e-core-tests/CHANGELOG.md",
|
||||
"node_modules/@woocommerce/api/dist/",
|
||||
"node_modules/@woocommerce/admin-e2e-tests/build",
|
||||
"node_modules/@woocommerce/classic-assets/build",
|
||||
"node_modules/@woocommerce/block-library/build",
|
||||
"node_modules/@woocommerce/block-library/blocks.ini",
|
||||
"node_modules/@woocommerce/admin-library/build",
|
||||
"package.json",
|
||||
"!node_modules/@woocommerce/admin-e2e-tests/*.ts.map",
|
||||
"!node_modules/@woocommerce/admin-e2e-tests/*.tsbuildinfo",
|
||||
|
|
2270
pnpm-lock.yaml
2270
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue