From ffc2d6636f18e7dfdb3787d53378b8b35d7b04c6 Mon Sep 17 00:00:00 2001 From: Marco Ciampini Date: Fri, 4 Mar 2022 11:54:38 +0100 Subject: [PATCH] Initial work --- .../line-height-control/index.native.js | 5 +- .../src/unit-control/index.native.js | 85 ++++++++++++++----- 2 files changed, 70 insertions(+), 20 deletions(-) diff --git a/packages/block-editor/src/components/line-height-control/index.native.js b/packages/block-editor/src/components/line-height-control/index.native.js index c48ca0aa5a35f2..2d1f024e87cc5a 100644 --- a/packages/block-editor/src/components/line-height-control/index.native.js +++ b/packages/block-editor/src/components/line-height-control/index.native.js @@ -12,6 +12,8 @@ export default function LineHeightControl( { value: lineHeight, onChange } ) { const isDefined = isLineHeightDefined( lineHeight ); const value = isDefined ? lineHeight : BASE_DEFAULT_VALUE; return ( + // If there's no units, this should be a `NumberControl` ? + // Alternatively, use `disableUnits` prop. ); } diff --git a/packages/components/src/unit-control/index.native.js b/packages/components/src/unit-control/index.native.js index d6f63f0a98447c..cea5cb8b67bc67 100644 --- a/packages/components/src/unit-control/index.native.js +++ b/packages/components/src/unit-control/index.native.js @@ -16,7 +16,13 @@ import RangeCell from '../mobile/bottom-sheet/range-cell'; import StepperCell from '../mobile/bottom-sheet/stepper-cell'; import Picker from '../mobile/picker'; import styles from './style.scss'; -import { CSS_UNITS, hasUnits, getAccessibleLabelForUnit } from './utils'; +import { + CSS_UNITS, + hasUnits, + getAccessibleLabelForUnit, + getUnitsWithCurrentUnit, + getParsedQuantityAndUnit, +} from './utils'; /** * WordPress dependencies @@ -25,19 +31,37 @@ import { useRef, useCallback, useMemo, memo } from '@wordpress/element'; import { withPreferredColorScheme } from '@wordpress/compose'; import { __, sprintf } from '@wordpress/i18n'; +const shouldShowPicker = ( units ) => { + return hasUnits( units ) && units?.length > 1; +}; + +/** + * Notes: + * - Goal: we want to stop using `false` as a value for 'UNITS' + * - The internal logic should be: + * - The units array should have a list of allowed units + * - Therefore, if the `units` prop is an empty array, there shouldn't be any UI shown for the unit, and the rawValue's unit should be `undefined` + * + * + * - The Native UnitControl's internal logic still relies on `unit` holding the `unit value` and `value` holding the `quantity` + * - Use `getParsedQuantityAndUnit` to take into account value, unit and units and parse the resulting unit + * - Render the button only if `units` has at least 1 item, and render the select if it has at least 2 items. + */ + function UnitControl( { currentInput, label, - value, + value: valueProp, onChange, onUnitChange, initialPosition, min, max, separatorType, - units = CSS_UNITS, - unit, + units: unitsProp = CSS_UNITS, + unit: unitProp, getStylesFromColorScheme, + disableUnits, ...props } ) { const pickerRef = useRef(); @@ -49,18 +73,34 @@ function UnitControl( { } }, [ pickerRef?.current ] ); - const currentInputValue = currentInput === null ? value : currentInput; + // Force value to `undefined` in case it was `null`. + const currentInputValue = + ( currentInput === null ? valueProp : currentInput ) ?? undefined; const initialControlValue = isFinite( currentInputValue ) ? currentInputValue : initialPosition; + const nonNullValueProp = initialControlValue ?? undefined; + const units = useMemo( + () => getUnitsWithCurrentUnit( nonNullValueProp, unitProp, unitsProp ), + [ nonNullValueProp, unitProp, unitsProp ] + ); + const [ parsedQuantity, parsedUnit ] = getParsedQuantityAndUnit( + nonNullValueProp, + unitProp, + units + ); + const unitButtonTextStyle = getStylesFromColorScheme( styles.unitButtonText, styles.unitButtonTextDark ); - /* translators: accessibility text. Inform about current unit value. %s: Current unit value. */ - const accessibilityLabel = sprintf( __( 'Current unit is %s' ), unit ); + const accessibilityLabel = sprintf( + /* translators: accessibility text. Inform about current unit value. %s: Current unit value. */ + __( 'Current unit is %s' ), + parsedUnit + ); const accessibilityHint = Platform.OS === 'ios' @@ -70,11 +110,11 @@ function UnitControl( { const renderUnitButton = useMemo( () => { const unitButton = ( - { unit } + { parsedUnit } ); - if ( hasUnits( units ) && units?.length > 1 ) { + if ( shouldShowPicker( units ) ) { return ( { // Keeping for legacy reasons, although `false` should not be a valid // value for the `units` prop anymore. - if ( units === false ) { + if ( disableUnits || units === false ) { return null; } return ( + { /* + * If units is an array of at least 2 items, show an interactive unit text, + * that opens a picker when tapped. + * Otherwise, just show the same text (but not interactive) + */ } { renderUnitButton } - { hasUnits( units ) && units?.length > 1 ? ( + { shouldShowPicker( units ) ? ( option.value === unit ); + const activeUnit = units.find( + ( option ) => option.value === parsedUnit + ); step = activeUnit?.step ?? 1; } @@ -153,20 +200,20 @@ function UnitControl( { return ( <> - { unit !== '%' ? ( + { parsedUnit !== '%' ? ( { renderUnitPicker() } @@ -177,14 +224,14 @@ function UnitControl( { onChange={ onChange } minimumValue={ min } maximumValue={ max } - value={ value } + value={ parsedQuantity } step={ step } - unit={ unit } + unit={ parsedUnit } defaultValue={ initialControlValue } separatorType={ separatorType } decimalNum={ decimalNum } openUnitPicker={ onPickerPresent } - unitLabel={ getAccessibleLabelForUnit( unit ) } + unitLabel={ getAccessibleLabelForUnit( parsedUnit ) } { ...props } > { renderUnitPicker() }