Update Cart & Checkout i2 temporarily locking to be on the parent block (https://github.com/woocommerce/woocommerce-blocks/pull/4837)
* update locking to be on parent, not block * include cart as well
This commit is contained in:
parent
a2f39d07f1
commit
f9f70893e0
|
@ -28,7 +28,7 @@ import { Icon, filledCart, removeCart } from '@woocommerce/icons';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import './editor.scss';
|
||||
import { addClassToBody } from './hacks';
|
||||
import { addClassToBody, useBlockPropsWithLocking } from './hacks';
|
||||
import { useViewSwitcher } from './use-view-switcher';
|
||||
import type { Attributes } from './types';
|
||||
import { CartBlockControlsContext } from './context';
|
||||
|
@ -184,12 +184,14 @@ export const Edit = ( {
|
|||
],
|
||||
[ 'woocommerce/empty-cart-block', {}, [] ],
|
||||
];
|
||||
return (
|
||||
<div
|
||||
className={ classnames( className, 'wp-block-woocommerce-cart', {
|
||||
const blockProps = useBlockPropsWithLocking( {
|
||||
className: classnames( className, 'wp-block-woocommerce-cart', {
|
||||
'is-editor-preview': attributes.isPreview,
|
||||
} ) }
|
||||
>
|
||||
} ),
|
||||
} );
|
||||
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<BlockErrorBoundary
|
||||
header={ __(
|
||||
'Cart Block Error',
|
||||
|
|
|
@ -17,11 +17,12 @@ import {
|
|||
store as blockEditorStore,
|
||||
} from '@wordpress/block-editor';
|
||||
import { isTextField } from '@wordpress/dom';
|
||||
import { useSelect, subscribe, select as _select } from '@wordpress/data';
|
||||
import { subscribe, select as _select } from '@wordpress/data';
|
||||
import { useEffect, useRef } from '@wordpress/element';
|
||||
import { MutableRefObject } from 'react';
|
||||
import { BACKSPACE, DELETE } from '@wordpress/keycodes';
|
||||
import { hasFilter } from '@wordpress/hooks';
|
||||
import { getBlockType } from '@wordpress/blocks';
|
||||
/**
|
||||
* Toggle class on body.
|
||||
*
|
||||
|
@ -73,64 +74,91 @@ export const addClassToBody = (): void => {
|
|||
}
|
||||
};
|
||||
|
||||
const isBlockLocked = ( clientId: string ): boolean => {
|
||||
if ( ! clientId ) {
|
||||
return false;
|
||||
}
|
||||
const { getBlock } = _select( blockEditorStore );
|
||||
const block = getBlock( clientId );
|
||||
// If lock.remove is defined at the block instance (not using the default value)
|
||||
// Then we use it.
|
||||
if ( typeof block?.attributes?.lock?.remove === 'boolean' ) {
|
||||
return block.attributes.lock.remove;
|
||||
}
|
||||
|
||||
// If we don't have lock on the block instance, we check the type
|
||||
const blockType = getBlockType( block.name );
|
||||
if ( typeof blockType?.attributes?.lock?.default?.remove === 'boolean' ) {
|
||||
return blockType?.attributes?.lock?.default?.remove;
|
||||
}
|
||||
// If nothing is defined, return false
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a hook we use in conjunction with useBlockProps. Its goal is to check if a block is locked (move or remove)
|
||||
* and will stop the keydown event from propagating to stop it from being deleted via the keyboard.
|
||||
* This is a hook we use in conjunction with useBlockProps. Its goal is to check if of the block's children is locked and being deleted.
|
||||
* It will stop the keydown event from propagating to stop it from being deleted via the keyboard.
|
||||
*
|
||||
* @todo Disable custom locking support if native support is detected.
|
||||
*/
|
||||
const useLockBlock = ( {
|
||||
clientId,
|
||||
const useLockedChildren = ( {
|
||||
ref,
|
||||
attributes,
|
||||
}: {
|
||||
clientId: string;
|
||||
ref: MutableRefObject< Element | undefined >;
|
||||
attributes: Record< string, unknown >;
|
||||
ref: MutableRefObject< HTMLElement | undefined >;
|
||||
} ): void => {
|
||||
const lockInCore = hasFilter(
|
||||
'blocks.registerBlockType',
|
||||
'core/lock/addAttribute'
|
||||
);
|
||||
const { isSelected } = useSelect(
|
||||
( select ) => {
|
||||
return {
|
||||
isSelected: select( blockEditorStore ).isBlockSelected(
|
||||
clientId
|
||||
),
|
||||
};
|
||||
},
|
||||
[ clientId ]
|
||||
);
|
||||
|
||||
const node = ref.current;
|
||||
|
||||
return useEffect( () => {
|
||||
if ( ! isSelected || ! node || lockInCore ) {
|
||||
if ( ! node || lockInCore ) {
|
||||
return;
|
||||
}
|
||||
function onKeyDown( event: KeyboardEvent ) {
|
||||
const { keyCode, target } = event;
|
||||
|
||||
if ( ! ( target instanceof HTMLElement ) ) {
|
||||
return;
|
||||
}
|
||||
// We're not trying to delete something here.
|
||||
if ( keyCode !== BACKSPACE && keyCode !== DELETE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( target !== node || isTextField( target ) ) {
|
||||
// We're in a field, so we should let text be deleted.
|
||||
if ( isTextField( target ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Typecast to fix issue with isTextField.
|
||||
const targetNode = target as HTMLElement;
|
||||
|
||||
// Our target isn't a block.
|
||||
if ( targetNode.dataset.block === undefined ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const clientId = targetNode.dataset.block;
|
||||
const isLocked = isBlockLocked( clientId );
|
||||
// Prevent the keyboard event from propogating if it supports locking.
|
||||
if ( attributes?.lock?.remove ) {
|
||||
if ( isLocked ) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
}
|
||||
|
||||
node.addEventListener( 'keydown', onKeyDown, true );
|
||||
node.addEventListener( 'keydown', onKeyDown, {
|
||||
capture: true,
|
||||
passive: false,
|
||||
} );
|
||||
|
||||
return () => {
|
||||
node.removeEventListener( 'keydown', onKeyDown, true );
|
||||
node.removeEventListener( 'keydown', onKeyDown, {
|
||||
capture: true,
|
||||
} );
|
||||
};
|
||||
}, [ node, isSelected, lockInCore, attributes ] );
|
||||
}, [ node, lockInCore ] );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -139,13 +167,10 @@ const useLockBlock = ( {
|
|||
export const useBlockPropsWithLocking = (
|
||||
props: Record< string, unknown > = {}
|
||||
): Record< string, unknown > => {
|
||||
const ref = useRef< Element >();
|
||||
const { attributes } = props;
|
||||
const ref = useRef< HTMLElement >();
|
||||
const blockProps = useBlockProps( { ref, ...props } );
|
||||
useLockBlock( {
|
||||
useLockedChildren( {
|
||||
ref,
|
||||
attributes,
|
||||
clientId: blockProps[ 'data-block' ],
|
||||
} );
|
||||
return blockProps;
|
||||
};
|
||||
|
|
|
@ -14,7 +14,6 @@ import classnames from 'classnames';
|
|||
*/
|
||||
import Block from './block';
|
||||
import './editor.scss';
|
||||
import { useBlockPropsWithLocking } from '../../hacks';
|
||||
|
||||
/**
|
||||
* Renders a placeholder in the editor.
|
||||
|
@ -48,23 +47,13 @@ const NoExpressPaymentMethodsPlaceholder = () => {
|
|||
);
|
||||
};
|
||||
|
||||
export const Edit = ( {
|
||||
attributes,
|
||||
}: {
|
||||
attributes: {
|
||||
lock: {
|
||||
move: boolean;
|
||||
remove: boolean;
|
||||
};
|
||||
};
|
||||
} ): JSX.Element | null => {
|
||||
export const Edit = (): JSX.Element | null => {
|
||||
const { paymentMethods, isInitialized } = useExpressPaymentMethods();
|
||||
const hasExpressPaymentMethods = Object.keys( paymentMethods ).length > 0;
|
||||
const blockProps = useBlockPropsWithLocking( {
|
||||
const blockProps = useBlockProps( {
|
||||
className: classnames( {
|
||||
'wp-block-woocommerce-cart-express-payment-block--has-express-payment-methods': hasExpressPaymentMethods,
|
||||
} ),
|
||||
attributes,
|
||||
} );
|
||||
|
||||
if ( ! isInitialized ) {
|
||||
|
|
|
@ -6,21 +6,10 @@ import { useBlockProps } from '@wordpress/block-editor';
|
|||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import { useBlockPropsWithLocking } from '../../hacks';
|
||||
|
||||
import Block from './block';
|
||||
|
||||
export const Edit = ( {
|
||||
attributes,
|
||||
}: {
|
||||
attributes: {
|
||||
lock: {
|
||||
move: boolean;
|
||||
remove: boolean;
|
||||
};
|
||||
};
|
||||
} ): JSX.Element => {
|
||||
const blockProps = useBlockPropsWithLocking( { attributes } );
|
||||
export const Edit = (): JSX.Element => {
|
||||
const blockProps = useBlockProps();
|
||||
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
|
|
|
@ -10,7 +10,6 @@ import { getSetting } from '@woocommerce/settings';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import Block from './block';
|
||||
import { useBlockPropsWithLocking } from '../../hacks';
|
||||
|
||||
export const Edit = ( {
|
||||
attributes,
|
||||
|
@ -27,7 +26,7 @@ export const Edit = ( {
|
|||
setAttributes: ( attributes: Record< string, unknown > ) => void;
|
||||
} ): JSX.Element => {
|
||||
const { showRateAfterTaxName, isShippingCalculatorEnabled } = attributes;
|
||||
const blockProps = useBlockPropsWithLocking( { attributes } );
|
||||
const blockProps = useBlockProps();
|
||||
const taxesEnabled = getSetting( 'taxesEnabled' ) as boolean;
|
||||
const displayItemizedTaxes = getSetting(
|
||||
'displayItemizedTaxes',
|
||||
|
|
|
@ -12,7 +12,6 @@ import { CART_PAGE_ID } from '@woocommerce/block-settings';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import Block from './block';
|
||||
import { useBlockPropsWithLocking } from '../../hacks';
|
||||
export const Edit = ( {
|
||||
attributes,
|
||||
setAttributes,
|
||||
|
@ -22,7 +21,7 @@ export const Edit = ( {
|
|||
};
|
||||
setAttributes: ( attributes: Record< string, unknown > ) => void;
|
||||
} ): JSX.Element => {
|
||||
const blockProps = useBlockPropsWithLocking( { attributes } );
|
||||
const blockProps = useBlockProps();
|
||||
const { checkoutPageId = 0 } = attributes;
|
||||
const { current: savedCheckoutPageId } = useRef( checkoutPageId );
|
||||
const currentPostId = useSelect(
|
||||
|
|
|
@ -35,7 +35,7 @@ import { CartCheckoutCompatibilityNotice } from '@woocommerce/editor-components/
|
|||
*/
|
||||
import './styles/editor.scss';
|
||||
import { Columns } from './columns';
|
||||
import { addClassToBody } from './hacks';
|
||||
import { addClassToBody, useBlockPropsWithLocking } from './hacks';
|
||||
import { CheckoutBlockContext, CheckoutBlockControlsContext } from './context';
|
||||
import type { Attributes } from './types';
|
||||
|
||||
|
@ -260,9 +260,9 @@ export const Edit = ( {
|
|||
</PanelBody>
|
||||
</InspectorControls>
|
||||
);
|
||||
|
||||
const blockProps = useBlockPropsWithLocking();
|
||||
return (
|
||||
<>
|
||||
<div { ...blockProps }>
|
||||
<EditorProvider
|
||||
previewData={ { previewCart, previewSavedPaymentMethods } }
|
||||
>
|
||||
|
@ -305,7 +305,7 @@ export const Edit = ( {
|
|||
</CheckoutProvider>
|
||||
</EditorProvider>
|
||||
<CartCheckoutCompatibilityNotice blockName="checkout" />
|
||||
</>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
|
|
|
@ -3,14 +3,17 @@
|
|||
*/
|
||||
import { __ } from '@wordpress/i18n';
|
||||
import classnames from 'classnames';
|
||||
import { PlainText, InspectorControls } from '@wordpress/block-editor';
|
||||
import {
|
||||
PlainText,
|
||||
InspectorControls,
|
||||
useBlockProps,
|
||||
} from '@wordpress/block-editor';
|
||||
import { PanelBody, ToggleControl } from '@wordpress/components';
|
||||
|
||||
/**
|
||||
* Internal dependencies
|
||||
*/
|
||||
import FormStepHeading from './form-step-heading';
|
||||
import { useBlockPropsWithLocking } from '../hacks';
|
||||
export interface FormStepBlockProps {
|
||||
attributes: { title: string; description: string; showStepNumber: boolean };
|
||||
setAttributes: ( attributes: Record< string, unknown > ) => void;
|
||||
|
@ -29,11 +32,10 @@ export const FormStepBlock = ( {
|
|||
children,
|
||||
}: FormStepBlockProps ): JSX.Element => {
|
||||
const { title = '', description = '', showStepNumber = true } = attributes;
|
||||
const blockProps = useBlockPropsWithLocking( {
|
||||
const blockProps = useBlockProps( {
|
||||
className: classnames( 'wc-block-components-checkout-step', className, {
|
||||
'wc-block-components-checkout-step--with-step-number': showStepNumber,
|
||||
} ),
|
||||
attributes,
|
||||
} );
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
|
|
|
@ -17,11 +17,12 @@ import {
|
|||
store as blockEditorStore,
|
||||
} from '@wordpress/block-editor';
|
||||
import { isTextField } from '@wordpress/dom';
|
||||
import { useSelect, subscribe, select as _select } from '@wordpress/data';
|
||||
import { subscribe, select as _select } from '@wordpress/data';
|
||||
import { useEffect, useRef } from '@wordpress/element';
|
||||
import { MutableRefObject } from 'react';
|
||||
import { BACKSPACE, DELETE } from '@wordpress/keycodes';
|
||||
import { hasFilter } from '@wordpress/hooks';
|
||||
import { getBlockType } from '@wordpress/blocks';
|
||||
/**
|
||||
* Toggle class on body.
|
||||
*
|
||||
|
@ -73,64 +74,91 @@ export const addClassToBody = (): void => {
|
|||
}
|
||||
};
|
||||
|
||||
const isBlockLocked = ( clientId: string ): boolean => {
|
||||
if ( ! clientId ) {
|
||||
return false;
|
||||
}
|
||||
const { getBlock } = _select( blockEditorStore );
|
||||
const block = getBlock( clientId );
|
||||
// If lock.remove is defined at the block instance (not using the default value)
|
||||
// Then we use it.
|
||||
if ( typeof block?.attributes?.lock?.remove === 'boolean' ) {
|
||||
return block.attributes.lock.remove;
|
||||
}
|
||||
|
||||
// If we don't have lock on the block instance, we check the type
|
||||
const blockType = getBlockType( block.name );
|
||||
if ( typeof blockType?.attributes?.lock?.default?.remove === 'boolean' ) {
|
||||
return blockType?.attributes?.lock?.default?.remove;
|
||||
}
|
||||
// If nothing is defined, return false
|
||||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* This is a hook we use in conjunction with useBlockProps. Its goal is to check if a block is locked (move or remove)
|
||||
* and will stop the keydown event from propagating to stop it from being deleted via the keyboard.
|
||||
* This is a hook we use in conjunction with useBlockProps. Its goal is to check if of the block's children is locked and being deleted.
|
||||
* It will stop the keydown event from propagating to stop it from being deleted via the keyboard.
|
||||
*
|
||||
* @todo Disable custom locking support if native support is detected.
|
||||
*/
|
||||
const useLockBlock = ( {
|
||||
clientId,
|
||||
const useLockedChildren = ( {
|
||||
ref,
|
||||
attributes,
|
||||
}: {
|
||||
clientId: string;
|
||||
ref: MutableRefObject< Element | undefined >;
|
||||
attributes: Record< string, unknown >;
|
||||
ref: MutableRefObject< HTMLElement | undefined >;
|
||||
} ): void => {
|
||||
const lockInCore = hasFilter(
|
||||
'blocks.registerBlockType',
|
||||
'core/lock/addAttribute'
|
||||
);
|
||||
const { isSelected } = useSelect(
|
||||
( select ) => {
|
||||
return {
|
||||
isSelected: select( blockEditorStore ).isBlockSelected(
|
||||
clientId
|
||||
),
|
||||
};
|
||||
},
|
||||
[ clientId ]
|
||||
);
|
||||
|
||||
const node = ref.current;
|
||||
|
||||
return useEffect( () => {
|
||||
if ( ! isSelected || ! node || lockInCore ) {
|
||||
if ( ! node || lockInCore ) {
|
||||
return;
|
||||
}
|
||||
function onKeyDown( event: KeyboardEvent ) {
|
||||
const { keyCode, target } = event;
|
||||
|
||||
if ( ! ( target instanceof HTMLElement ) ) {
|
||||
return;
|
||||
}
|
||||
// We're not trying to delete something here.
|
||||
if ( keyCode !== BACKSPACE && keyCode !== DELETE ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( target !== node || isTextField( target ) ) {
|
||||
// We're in a field, so we should let text be deleted.
|
||||
if ( isTextField( target ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Typecast to fix issue with isTextField.
|
||||
const targetNode = target as HTMLElement;
|
||||
|
||||
// Our target isn't a block.
|
||||
if ( targetNode.dataset.block === undefined ) {
|
||||
return;
|
||||
}
|
||||
|
||||
const clientId = targetNode.dataset.block;
|
||||
const isLocked = isBlockLocked( clientId );
|
||||
// Prevent the keyboard event from propogating if it supports locking.
|
||||
if ( attributes?.lock?.remove ) {
|
||||
if ( isLocked ) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
event.stopImmediatePropagation();
|
||||
}
|
||||
}
|
||||
|
||||
node.addEventListener( 'keydown', onKeyDown, true );
|
||||
node.addEventListener( 'keydown', onKeyDown, {
|
||||
capture: true,
|
||||
passive: false,
|
||||
} );
|
||||
|
||||
return () => {
|
||||
node.removeEventListener( 'keydown', onKeyDown, true );
|
||||
node.removeEventListener( 'keydown', onKeyDown, {
|
||||
capture: true,
|
||||
} );
|
||||
};
|
||||
}, [ node, isSelected, lockInCore, attributes ] );
|
||||
}, [ node, lockInCore ] );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -139,13 +167,10 @@ const useLockBlock = ( {
|
|||
export const useBlockPropsWithLocking = (
|
||||
props: Record< string, unknown > = {}
|
||||
): Record< string, unknown > => {
|
||||
const ref = useRef< Element >();
|
||||
const { attributes } = props;
|
||||
const ref = useRef< HTMLElement >();
|
||||
const blockProps = useBlockProps( { ref, ...props } );
|
||||
useLockBlock( {
|
||||
useLockedChildren( {
|
||||
ref,
|
||||
attributes,
|
||||
clientId: blockProps[ 'data-block' ],
|
||||
} );
|
||||
return blockProps;
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ import { CHECKOUT_PAGE_ID } from '@woocommerce/block-settings';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import Block from './block';
|
||||
import { useBlockPropsWithLocking } from '../../hacks';
|
||||
|
||||
export const Edit = ( {
|
||||
attributes,
|
||||
setAttributes,
|
||||
|
@ -23,7 +23,7 @@ export const Edit = ( {
|
|||
};
|
||||
setAttributes: ( attributes: Record< string, unknown > ) => void;
|
||||
} ): JSX.Element => {
|
||||
const blockProps = useBlockPropsWithLocking( { attributes } );
|
||||
const blockProps = useBlockProps();
|
||||
const { cartPageId = 0, showReturnToCart = true } = attributes;
|
||||
const { current: savedCartPageId } = useRef( cartPageId );
|
||||
const currentPostId = useSelect(
|
||||
|
|
|
@ -14,7 +14,6 @@ import classnames from 'classnames';
|
|||
*/
|
||||
import Block from './block';
|
||||
import './editor.scss';
|
||||
import { useBlockPropsWithLocking } from '../../hacks';
|
||||
|
||||
/**
|
||||
* Renders a placeholder in the editor.
|
||||
|
@ -60,7 +59,7 @@ export const Edit = ( {
|
|||
} ): JSX.Element | null => {
|
||||
const { paymentMethods, isInitialized } = useExpressPaymentMethods();
|
||||
const hasExpressPaymentMethods = Object.keys( paymentMethods ).length > 0;
|
||||
const blockProps = useBlockPropsWithLocking( {
|
||||
const blockProps = useBlockProps( {
|
||||
className: classnames( {
|
||||
'wp-block-woocommerce-checkout-express-payment-block--has-express-payment-methods': hasExpressPaymentMethods,
|
||||
} ),
|
||||
|
|
|
@ -9,19 +9,9 @@ import { Disabled } from '@wordpress/components';
|
|||
*/
|
||||
import Block from './block';
|
||||
import './editor.scss';
|
||||
import { useBlockPropsWithLocking } from '../../hacks';
|
||||
|
||||
export const Edit = ( {
|
||||
attributes,
|
||||
}: {
|
||||
attributes: {
|
||||
lock: {
|
||||
move: boolean;
|
||||
remove: boolean;
|
||||
};
|
||||
};
|
||||
} ): JSX.Element => {
|
||||
const blockProps = useBlockPropsWithLocking( { attributes } );
|
||||
export const Edit = (): JSX.Element => {
|
||||
const blockProps = useBlockProps();
|
||||
return (
|
||||
<div { ...blockProps }>
|
||||
<Disabled>
|
||||
|
|
|
@ -10,7 +10,6 @@ import { getSetting } from '@woocommerce/settings';
|
|||
* Internal dependencies
|
||||
*/
|
||||
import Block from './block';
|
||||
import { useBlockPropsWithLocking } from '../../hacks';
|
||||
|
||||
export const Edit = ( {
|
||||
attributes,
|
||||
|
@ -25,7 +24,7 @@ export const Edit = ( {
|
|||
};
|
||||
setAttributes: ( attributes: Record< string, unknown > ) => void;
|
||||
} ): JSX.Element => {
|
||||
const blockProps = useBlockPropsWithLocking( { attributes } );
|
||||
const blockProps = useBlockProps();
|
||||
const taxesEnabled = getSetting( 'taxesEnabled' ) as boolean;
|
||||
const displayItemizedTaxes = getSetting(
|
||||
'displayItemizedTaxes',
|
||||
|
|
Loading…
Reference in New Issue