import { __ } from '@wordpress/i18n'; import { BaseControl, __experimentalNumberControl as NumberControl, SelectControl, __experimentalHStack as HStack } from '@wordpress/components'; import { useState, useEffect } from 'react'; /** * Control component with a number input and a select dropdown for units (px, rem, em, % etc.). * Accepts a default value as a string (e.g., "15px", "10rem", etc.). * Includes an optional 'auto' unit if includeAuto is true, and handles autoReturnsNull behavior. */ export function DimensionValueControl({ value = '10px', onChange, includeAuto = false, autoReturnsNull = false }) { // Options for select control (CSS units) including 'auto' if enabled const unitOptions = [ { label: __('px'), value: 'px' }, { label: __('%'), value: '%' }, { label: __('em'), value: 'em' }, { label: __('rem'), value: 'rem' }, { label: __('vw'), value: 'vw' }, { label: __('vh'), value: 'vh' }, ...(includeAuto ? [{ label: __('auto'), value: 'auto' }] : []), // Add 'auto' option if includeAuto is true ]; // Parse the value string into a number and unit const parseValue = (value) => { const regex = /([0-9]+)([a-zA-Z%]+)?/; // Capture the number and the unit const match = value.match(regex); if (match) { return { numberValue: parseInt(match[1], 10), // Number part unitValue: match[2] || 'px' // Unit part (default to 'px' if no unit found) }; } return { numberValue: 0, unitValue: 'px' }; // Fallback if invalid format }; // Use the parsed value to set initial state const { numberValue: initialNumber, unitValue: initialUnit } = parseValue(value); const [numberValue, setNumberValue] = useState(initialNumber); const [unitValue, setUnitValue] = useState(initialUnit); // Combine the number and unit into a string like "15px" const dimensionValue = `${numberValue}${unitValue}`; // Handle number change const onNumberChange = (newValue) => { setNumberValue(newValue); if (onChange && unitValue !== 'auto') { onChange(`${newValue}${unitValue}`); // Pass updated value back to parent } }; // Handle unit change const onUnitChange = (newUnit) => { if (newUnit === 'auto') { setNumberValue(null); // Reset the number value when 'auto' is selected } setUnitValue(newUnit); if (onChange) { const updatedValue = newUnit === 'auto' ? (autoReturnsNull ? null : 'auto') : `${numberValue}${newUnit}`; // Pass 'auto' or null or updated value back to parent onChange(updatedValue); } }; // Effect to handle when value prop changes (useful for syncing) useEffect(() => { const { numberValue, unitValue } = parseValue(value); setNumberValue(numberValue); setUnitValue(unitValue); }, [value]); return ( {/* Number input control, disabled when 'auto' is selected */} {/* Select dropdown control for units */} ); }