diff --git a/packages/js/product-editor/changelog/add-step-buttons b/packages/js/product-editor/changelog/add-step-buttons new file mode 100644 index 00000000000..fe84d148c82 --- /dev/null +++ b/packages/js/product-editor/changelog/add-step-buttons @@ -0,0 +1,4 @@ +Significance: minor +Type: add + +Add step buttons for Number block and component diff --git a/packages/js/product-editor/src/components/number-control/number-control.tsx b/packages/js/product-editor/src/components/number-control/number-control.tsx index 80f512e5baa..f055a164961 100644 --- a/packages/js/product-editor/src/components/number-control/number-control.tsx +++ b/packages/js/product-editor/src/components/number-control/number-control.tsx @@ -1,11 +1,20 @@ /** * External dependencies */ -import { createElement } from '@wordpress/element'; +import { + createElement, + Fragment, + useEffect, + useRef, + useState, +} from '@wordpress/element'; import { useInstanceId } from '@wordpress/compose'; import classNames from 'classnames'; +import { plus, reset } from '@wordpress/icons'; +import { __ } from '@wordpress/i18n'; import { BaseControl, + Button, // @ts-expect-error `__experimentalInputControl` does exist. __experimentalInputControl as InputControl, } from '@wordpress/components'; @@ -43,14 +52,45 @@ export const NumberControl: React.FC< NumberProps > = ( { tooltip, placeholder, disabled, - step, + step = 1, }: NumberProps ) => { + const id = useInstanceId( BaseControl, 'product_number_field' ) as string; + const [ isFocused, setIsFocused ] = useState( false ); + const unfocusIfOutside = ( event: React.FocusEvent ) => { + if ( + ! document + .getElementById( id ) + ?.parentElement?.contains( event.relatedTarget ) + ) { + setIsFocused( false ); + onBlur?.(); + } + }; const inputProps = useNumberInputProps( { value: value || '', onChange, + onFocus: () => setIsFocused( true ), } ); - const id = useInstanceId( BaseControl, 'product_number_field' ) as string; + const [ increment, setIncrement ] = useState( 0 ); + + const timeoutRef = useRef< number | null >( null ); + + const incrementValue = () => + onChange( String( parseFloat( value || '0' ) + increment ) ); + + useEffect( () => { + if ( increment !== 0 ) { + timeoutRef.current = setTimeout( incrementValue, 100 ); + } else if ( timeoutRef.current ) { + clearTimeout( timeoutRef.current ); + } + return () => { + if ( timeoutRef.current ) { + clearTimeout( timeoutRef.current ); + } + }; + }, [ increment, value ] ); return ( = ( { { ...inputProps } step={ step } disabled={ disabled } + autoComplete="off" id={ id } - suffix={ suffix } + className="woocommerce-number-control" + suffix={ + <> + { suffix } + { isFocused && ( + <> +