@wordpress/block-editor
Version:
330 lines (329 loc) • 10 kB
JavaScript
/**
* WordPress dependencies
*/
import { Button, Icon, RangeControl, __experimentalHStack as HStack, __experimentalUnitControl as UnitControl, __experimentalUseCustomUnits as useCustomUnits, __experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue, CustomSelectControl } from '@wordpress/components';
import { useSelect } from '@wordpress/data';
import { useState, useMemo } from '@wordpress/element';
import { usePrevious } from '@wordpress/compose';
import { __, _x, sprintf } from '@wordpress/i18n';
import { settings } from '@wordpress/icons';
/**
* Internal dependencies
*/
import { useSettings } from '../../use-settings';
import { store as blockEditorStore } from '../../../store';
import { RANGE_CONTROL_MAX_SIZE, ALL_SIDES, LABELS, getSliderValueFromPreset, getCustomValueFromPreset, getPresetValueFromCustomValue, isValueSpacingPreset } from '../utils';
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
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
},
svw: {
max: 100,
steps: 1
},
lvw: {
max: 100,
steps: 1
},
dvw: {
max: 100,
steps: 1
},
svh: {
max: 100,
steps: 1
},
lvh: {
max: 100,
steps: 1
},
dvh: {
max: 100,
steps: 1
},
vi: {
max: 100,
steps: 1
},
svi: {
max: 100,
steps: 1
},
lvi: {
max: 100,
steps: 1
},
dvi: {
max: 100,
steps: 1
},
vb: {
max: 100,
steps: 1
},
svb: {
max: 100,
steps: 1
},
lvb: {
max: 100,
steps: 1
},
dvb: {
max: 100,
steps: 1
},
vmin: {
max: 100,
steps: 1
},
svmin: {
max: 100,
steps: 1
},
lvmin: {
max: 100,
steps: 1
},
dvmin: {
max: 100,
steps: 1
},
vmax: {
max: 100,
steps: 1
},
svmax: {
max: 100,
steps: 1
},
lvmax: {
max: 100,
steps: 1
},
dvmax: {
max: 100,
steps: 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 <= RANGE_CONTROL_MAX_SIZE;
const disableCustomSpacingSizes = useSelect(select => {
const editorSettings = select(blockEditorStore).getSettings();
return editorSettings?.disableCustomSpacingSizes;
});
const [showCustomValueControl, setShowCustomValueControl] = useState(!disableCustomSpacingSizes && value !== undefined && !isValueSpacingPreset(value));
const [minValue, setMinValue] = useState(minimumCustomValue);
const previousValue = usePrevious(value);
if (!!value && previousValue !== value && !isValueSpacingPreset(value) && showCustomValueControl !== true) {
setShowCustomValueControl(true);
}
const [availableUnits] = useSettings('spacing.units');
const units = useCustomUnits({
availableUnits: availableUnits || ['px', 'em', 'rem']
});
let currentValue = null;
const showCustomValueInSelectList = !showRangeControl && !showCustomValueControl && value !== undefined && (!isValueSpacingPreset(value) || isValueSpacingPreset(value) && isMixed);
if (showCustomValueInSelectList) {
selectListSizes = [...spacingSizes, {
name: !isMixed ?
// translators: %s: A custom measurement, e.g. 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.slice(1, spacingSizes.length - 1).map((_newValue, index) => ({
value: index + 1,
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 etc.). 2. Type of spacing being modified (padding, margin, etc).
_x('%1$s %2$s', 'spacing'), sideLabel, typeLabel).trim();
return /*#__PURE__*/_jsxs(HStack, {
className: "spacing-sizes-control__wrapper",
children: [icon && /*#__PURE__*/_jsx(Icon, {
className: "spacing-sizes-control__icon",
icon: icon,
size: 24
}), showCustomValueControl && /*#__PURE__*/_jsxs(_Fragment, {
children: [/*#__PURE__*/_jsx(UnitControl, {
onMouseOver: onMouseOver,
onMouseOut: onMouseOut,
onFocus: onMouseOver,
onBlur: onMouseOut,
onChange: newSize => onChange(getNewCustomValue(newSize)),
value: currentValue,
units: units,
min: minValue,
placeholder: allPlaceholder,
disableUnits: isMixed,
label: ariaLabel,
hideLabelFromVision: true,
className: "spacing-sizes-control__custom-value-input",
size: "__unstable-large",
onDragStart: () => {
if (value?.charAt(0) === '-') {
setMinValue(0);
}
},
onDrag: () => {
if (value?.charAt(0) === '-') {
setMinValue(0);
}
},
onDragEnd: () => {
setMinValue(minimumCustomValue);
}
}), /*#__PURE__*/_jsx(RangeControl, {
__next40pxDefaultSize: true,
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,
label: ariaLabel,
hideLabelFromVision: true
})]
}), showRangeControl && !showCustomValueControl && /*#__PURE__*/_jsx(RangeControl, {
__next40pxDefaultSize: true,
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 && /*#__PURE__*/_jsx(CustomSelectControl, {
className: "spacing-sizes-control__custom-select-control",
value:
// passing empty string as a fallback to continue using the
// component in controlled mode
options.find(option => option.key === currentValue) || '',
onChange: selection => {
onChange(getNewPresetValue(selection.selectedItem.key, 'selectList'));
},
options: options,
label: ariaLabel,
hideLabelFromVision: true,
size: "__unstable-large",
onMouseOver: onMouseOver,
onMouseOut: onMouseOut,
onFocus: onMouseOver,
onBlur: onMouseOut
}), !disableCustomSpacingSizes && /*#__PURE__*/_jsx(Button, {
label: showCustomValueControl ? __('Use size preset') : __('Set custom size'),
icon: settings,
onClick: () => {
setShowCustomValueControl(!showCustomValueControl);
},
isPressed: showCustomValueControl,
size: "small",
className: "spacing-sizes-control__custom-toggle",
iconSize: 24
})]
});
}
//# sourceMappingURL=spacing-input-control.js.map