UNPKG

@wordpress/block-editor

Version:
233 lines (216 loc) 8.16 kB
import { createElement, Fragment } from "@wordpress/element"; /** * WordPress dependencies */ import { Button, CustomSelectControl, Icon, RangeControl, __experimentalHStack as HStack, __experimentalUnitControl as UnitControl, __experimentalUseCustomUnits as useCustomUnits, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue } from '@wordpress/components'; import { useSelect } from '@wordpress/data'; import { useState, useMemo } from '@wordpress/element'; import { usePrevious } from '@wordpress/compose'; import { __, sprintf } from '@wordpress/i18n'; import { settings } from '@wordpress/icons'; /** * Internal dependencies */ import useSetting from '../../use-setting'; import { store as blockEditorStore } from '../../../store'; import { ALL_SIDES, LABELS, getSliderValueFromPreset, getCustomValueFromPreset, getPresetValueFromCustomValue, isValueSpacingPreset } from '../utils'; const CUSTOM_VALUE_SETTINGS = { px: { max: 300, steps: 1 }, '%': { max: 100, steps: 1 }, vw: { max: 100, steps: 1 }, vh: { max: 100, steps: 1 }, em: { max: 10, steps: 0.1 }, rm: { max: 10, steps: 0.1 } }; export default function SpacingInputControl({ icon, isMixed = false, minimumCustomValue, onChange, onMouseOut, onMouseOver, showSideInLabel = true, side, spacingSizes, type, value }) { var _CUSTOM_VALUE_SETTING, _CUSTOM_VALUE_SETTING2; // Treat value as a preset value if the passed in value matches the value of one of the spacingSizes. value = getPresetValueFromCustomValue(value, spacingSizes); let selectListSizes = spacingSizes; const showRangeControl = spacingSizes.length <= 8; const disableCustomSpacingSizes = useSelect(select => { const editorSettings = select(blockEditorStore).getSettings(); return editorSettings?.disableCustomSpacingSizes; }); const [showCustomValueControl, setShowCustomValueControl] = useState(!disableCustomSpacingSizes && value !== undefined && !isValueSpacingPreset(value)); const previousValue = usePrevious(value); if (!!value && previousValue !== value && !isValueSpacingPreset(value) && showCustomValueControl !== true) { setShowCustomValueControl(true); } const units = useCustomUnits({ availableUnits: useSetting('spacing.units') || ['px', 'em', 'rem'] }); let currentValue = null; const showCustomValueInSelectList = !showRangeControl && !showCustomValueControl && value !== undefined && (!isValueSpacingPreset(value) || isValueSpacingPreset(value) && isMixed); if (showCustomValueInSelectList) { selectListSizes = [...spacingSizes, { name: !isMixed ? // translators: A custom measurement, eg. a number followed by a unit like 12px. sprintf(__('Custom (%s)'), value) : __('Mixed'), slug: 'custom', size: value }]; currentValue = selectListSizes.length - 1; } else if (!isMixed) { currentValue = !showCustomValueControl ? getSliderValueFromPreset(value, spacingSizes) : getCustomValueFromPreset(value, spacingSizes); } const selectedUnit = useMemo(() => parseQuantityAndUnitFromRawValue(currentValue), [currentValue])[1] || units[0].value; const setInitialValue = () => { if (value === undefined) { onChange('0'); } }; const customTooltipContent = newValue => value === undefined ? undefined : spacingSizes[newValue]?.name; const customRangeValue = parseFloat(currentValue, 10); const getNewCustomValue = newSize => { const isNumeric = !isNaN(parseFloat(newSize)); const nextValue = isNumeric ? newSize : undefined; return nextValue; }; const getNewPresetValue = (newSize, controlType) => { const size = parseInt(newSize, 10); if (controlType === 'selectList') { if (size === 0) { return undefined; } if (size === 1) { return '0'; } } else if (size === 0) { return '0'; } return `var:preset|spacing|${spacingSizes[newSize]?.slug}`; }; const handleCustomValueSliderChange = next => { onChange([next, selectedUnit].join('')); }; const allPlaceholder = isMixed ? __('Mixed') : null; const options = selectListSizes.map((size, index) => ({ key: index, name: size.name })); const marks = spacingSizes.map((_newValue, index) => ({ value: index, label: undefined })); const sideLabel = ALL_SIDES.includes(side) && showSideInLabel ? LABELS[side] : ''; const typeLabel = showSideInLabel ? type?.toLowerCase() : type; const ariaLabel = sprintf( // translators: 1: The side of the block being modified (top, bottom, left, All sides etc.). 2. Type of spacing being modified (Padding, margin, etc) __('%1$s %2$s'), sideLabel, typeLabel).trim(); return createElement(HStack, { className: "spacing-sizes-control__wrapper" }, icon && createElement(Icon, { className: "spacing-sizes-control__icon", icon: icon, size: 24 }), showCustomValueControl && createElement(Fragment, null, createElement(UnitControl, { onMouseOver: onMouseOver, onMouseOut: onMouseOut, onFocus: onMouseOver, onBlur: onMouseOut, onChange: newSize => onChange(getNewCustomValue(newSize)), value: currentValue, units: units, min: minimumCustomValue, placeholder: allPlaceholder, disableUnits: isMixed, label: ariaLabel, hideLabelFromVision: true, className: "spacing-sizes-control__custom-value-input", size: '__unstable-large' }), createElement(RangeControl, { onMouseOver: onMouseOver, onMouseOut: onMouseOut, onFocus: onMouseOver, onBlur: onMouseOut, value: customRangeValue, min: 0, max: (_CUSTOM_VALUE_SETTING = CUSTOM_VALUE_SETTINGS[selectedUnit]?.max) !== null && _CUSTOM_VALUE_SETTING !== void 0 ? _CUSTOM_VALUE_SETTING : 10, step: (_CUSTOM_VALUE_SETTING2 = CUSTOM_VALUE_SETTINGS[selectedUnit]?.steps) !== null && _CUSTOM_VALUE_SETTING2 !== void 0 ? _CUSTOM_VALUE_SETTING2 : 0.1, withInputField: false, onChange: handleCustomValueSliderChange, className: "spacing-sizes-control__custom-value-range", __nextHasNoMarginBottom: true })), showRangeControl && !showCustomValueControl && createElement(RangeControl, { onMouseOver: onMouseOver, onMouseOut: onMouseOut, className: "spacing-sizes-control__range-control", value: currentValue, onChange: newSize => onChange(getNewPresetValue(newSize)), onMouseDown: event => { // If mouse down is near start of range set initial value to 0, which // prevents the user have to drag right then left to get 0 setting. if (event?.nativeEvent?.offsetX < 35) { setInitialValue(); } }, withInputField: false, "aria-valuenow": currentValue, "aria-valuetext": spacingSizes[currentValue]?.name, renderTooltipContent: customTooltipContent, min: 0, max: spacingSizes.length - 1, marks: marks, label: ariaLabel, hideLabelFromVision: true, __nextHasNoMarginBottom: true, onFocus: onMouseOver, onBlur: onMouseOut }), !showRangeControl && !showCustomValueControl && createElement(CustomSelectControl, { className: "spacing-sizes-control__custom-select-control", value: options.find(option => option.key === currentValue) || '' // passing undefined here causes a downshift controlled/uncontrolled warning , onChange: selection => { onChange(getNewPresetValue(selection.selectedItem.key, 'selectList')); }, options: options, label: ariaLabel, hideLabelFromVision: true, __nextUnconstrainedWidth: true, size: '__unstable-large', onMouseOver: onMouseOver, onMouseOut: onMouseOut, onFocus: onMouseOver, onBlur: onMouseOut }), !disableCustomSpacingSizes && createElement(Button, { label: showCustomValueControl ? __('Use size preset') : __('Set custom size'), icon: settings, onClick: () => { setShowCustomValueControl(!showCustomValueControl); }, isPressed: showCustomValueControl, isSmall: true, className: "spacing-sizes-control__custom-toggle", iconSize: 24 })); } //# sourceMappingURL=spacing-input-control.js.map