UNPKG

@wordpress/block-editor

Version:
299 lines (298 loc) 9.72 kB
// packages/block-editor/src/components/spacing-sizes-control/input-controls/spacing-input-control.js 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"; 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 { Fragment, jsx, jsxs } from "react/jsx-runtime"; var 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 } }; function SpacingInputControl({ icon, isMixed = false, minimumCustomValue, onChange, onMouseOut, onMouseOver, showSideInLabel = true, side, spacingSizes, type, value }) { 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 !== void 0 && !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 !== void 0 && (!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 === void 0) { onChange("0"); } }; const customTooltipContent = (newValue) => value === void 0 ? void 0 : spacingSizes[newValue]?.name; const customRangeValue = parseFloat(currentValue, 10); const getNewCustomValue = (newSize) => { const isNumeric = !isNaN(parseFloat(newSize)); const nextValue = isNumeric ? newSize : void 0; return nextValue; }; const getNewPresetValue = (newSize, controlType) => { const size = parseInt(newSize, 10); if (controlType === "selectList") { if (size === 0) { return void 0; } 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: void 0 })); 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, size: 24 } ), showCustomValueControl && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( UnitControl, { onMouseOver, onMouseOut, onFocus: onMouseOver, onBlur: onMouseOut, onChange: (newSize) => onChange(getNewCustomValue(newSize)), value: currentValue, 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, onMouseOut, onFocus: onMouseOver, onBlur: onMouseOut, value: customRangeValue, min: 0, max: CUSTOM_VALUE_SETTINGS[selectedUnit]?.max ?? 10, step: CUSTOM_VALUE_SETTINGS[selectedUnit]?.steps ?? 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, onMouseOut, className: "spacing-sizes-control__range-control", value: currentValue, onChange: (newSize) => onChange(getNewPresetValue(newSize)), onMouseDown: (event) => { 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, 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, label: ariaLabel, hideLabelFromVision: true, size: "__unstable-large", onMouseOver, 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 } ) ] }); } export { SpacingInputControl as default }; //# sourceMappingURL=spacing-input-control.js.map