UNPKG

@wordpress/block-editor

Version:
550 lines (535 loc) 21.6 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = DimensionsPanel; exports.useHasDimensionsPanel = useHasDimensionsPanel; var _clsx = _interopRequireDefault(require("clsx")); var _i18n = require("@wordpress/i18n"); var _components = require("@wordpress/components"); var _icons = require("@wordpress/icons"); var _element = require("@wordpress/element"); var _utils = require("./utils"); var _spacingSizesControl = _interopRequireDefault(require("../spacing-sizes-control")); var _heightControl = _interopRequireDefault(require("../height-control")); var _childLayoutControl = _interopRequireDefault(require("../child-layout-control")); var _aspectRatioTool = _interopRequireDefault(require("../dimensions-tool/aspect-ratio-tool")); var _utils2 = require("../../hooks/utils"); var _object = require("../../utils/object"); var _jsxRuntime = require("react/jsx-runtime"); /** * External dependencies */ /** * WordPress dependencies */ /** * Internal dependencies */ const AXIAL_SIDES = ['horizontal', 'vertical']; function useHasDimensionsPanel(settings) { const hasContentSize = useHasContentSize(settings); const hasWideSize = useHasWideSize(settings); const hasPadding = useHasPadding(settings); const hasMargin = useHasMargin(settings); const hasGap = useHasGap(settings); const hasMinHeight = useHasMinHeight(settings); const hasAspectRatio = useHasAspectRatio(settings); const hasChildLayout = useHasChildLayout(settings); return _element.Platform.OS === 'web' && (hasContentSize || hasWideSize || hasPadding || hasMargin || hasGap || hasMinHeight || hasAspectRatio || hasChildLayout); } function useHasContentSize(settings) { return settings?.layout?.contentSize; } function useHasWideSize(settings) { return settings?.layout?.wideSize; } function useHasPadding(settings) { return settings?.spacing?.padding; } function useHasMargin(settings) { return settings?.spacing?.margin; } function useHasGap(settings) { return settings?.spacing?.blockGap; } function useHasMinHeight(settings) { return settings?.dimensions?.minHeight; } function useHasAspectRatio(settings) { return settings?.dimensions?.aspectRatio; } function useHasChildLayout(settings) { var _settings$parentLayou; const { type: parentLayoutType = 'default', default: { type: defaultParentLayoutType = 'default' } = {}, allowSizingOnChildren = false } = (_settings$parentLayou = settings?.parentLayout) !== null && _settings$parentLayou !== void 0 ? _settings$parentLayou : {}; const support = (defaultParentLayoutType === 'flex' || parentLayoutType === 'flex' || defaultParentLayoutType === 'grid' || parentLayoutType === 'grid') && allowSizingOnChildren; return !!settings?.layout && support; } function useHasSpacingPresets(settings) { const { defaultSpacingSizes, spacingSizes } = settings?.spacing || {}; return defaultSpacingSizes !== false && spacingSizes?.default?.length > 0 || spacingSizes?.theme?.length > 0 || spacingSizes?.custom?.length > 0; } function filterValuesBySides(values, sides) { // If no custom side configuration, all sides are opted into by default. // Without any values, we have nothing to filter either. if (!sides || !values) { return values; } // Only include sides opted into within filtered values. const filteredValues = {}; sides.forEach(side => { if (side === 'vertical') { filteredValues.top = values.top; filteredValues.bottom = values.bottom; } if (side === 'horizontal') { filteredValues.left = values.left; filteredValues.right = values.right; } filteredValues[side] = values?.[side]; }); return filteredValues; } function splitStyleValue(value) { // Check for shorthand value (a string value). if (value && typeof value === 'string') { // Convert to value for individual sides for BoxControl. return { top: value, right: value, bottom: value, left: value }; } return value; } function splitGapValue(value, isAxialGap) { if (!value) { return value; } // Check for shorthand value (a string value). if (typeof value === 'string') { /* * Map the string value to appropriate sides for the spacing control depending * on whether the current block has axial gap support or not. * * Note: The axial value pairs must match for the spacing control to display * the appropriate horizontal/vertical sliders. */ return isAxialGap ? { top: value, right: value, bottom: value, left: value } : { top: value }; } return { ...value, right: value?.left, bottom: value?.top }; } function DimensionsToolsPanel({ resetAllFilter, onChange, value, panelId, children }) { const dropdownMenuProps = (0, _utils.useToolsPanelDropdownMenuProps)(); const resetAll = () => { const updatedValue = resetAllFilter(value); onChange(updatedValue); }; return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanel, { label: (0, _i18n.__)('Dimensions'), resetAll: resetAll, panelId: panelId, dropdownMenuProps: dropdownMenuProps, children: children }); } const DEFAULT_CONTROLS = { contentSize: true, wideSize: true, padding: true, margin: true, blockGap: true, minHeight: true, aspectRatio: true, childLayout: true }; function DimensionsPanel({ as: Wrapper = DimensionsToolsPanel, value, onChange, inheritedValue = value, settings, panelId, defaultControls = DEFAULT_CONTROLS, onVisualize = () => {}, // Special case because the layout controls are not part of the dimensions panel // in global styles but not in block inspector. includeLayoutControls = false }) { var _defaultControls$cont, _defaultControls$wide, _defaultControls$padd, _defaultControls$marg, _defaultControls$bloc, _defaultControls$chil, _defaultControls$minH, _defaultControls$aspe; const { dimensions, spacing } = settings; const decodeValue = rawValue => { if (rawValue && typeof rawValue === 'object') { return Object.keys(rawValue).reduce((acc, key) => { acc[key] = (0, _utils.getValueFromVariable)({ settings: { dimensions, spacing } }, '', rawValue[key]); return acc; }, {}); } return (0, _utils.getValueFromVariable)({ settings: { dimensions, spacing } }, '', rawValue); }; const showSpacingPresetsControl = useHasSpacingPresets(settings); const units = (0, _components.__experimentalUseCustomUnits)({ availableUnits: settings?.spacing?.units || ['%', 'px', 'em', 'rem', 'vw'] }); //Minimum Margin Value const minimumMargin = -Infinity; const [minMarginValue, setMinMarginValue] = (0, _element.useState)(minimumMargin); // Content Width const showContentSizeControl = useHasContentSize(settings) && includeLayoutControls; const contentSizeValue = decodeValue(inheritedValue?.layout?.contentSize); const setContentSizeValue = newValue => { onChange((0, _object.setImmutably)(value, ['layout', 'contentSize'], newValue || undefined)); }; const hasUserSetContentSizeValue = () => !!value?.layout?.contentSize; const resetContentSizeValue = () => setContentSizeValue(undefined); // Wide Width const showWideSizeControl = useHasWideSize(settings) && includeLayoutControls; const wideSizeValue = decodeValue(inheritedValue?.layout?.wideSize); const setWideSizeValue = newValue => { onChange((0, _object.setImmutably)(value, ['layout', 'wideSize'], newValue || undefined)); }; const hasUserSetWideSizeValue = () => !!value?.layout?.wideSize; const resetWideSizeValue = () => setWideSizeValue(undefined); // Padding const showPaddingControl = useHasPadding(settings); const rawPadding = decodeValue(inheritedValue?.spacing?.padding); const paddingValues = splitStyleValue(rawPadding); const paddingSides = Array.isArray(settings?.spacing?.padding) ? settings?.spacing?.padding : settings?.spacing?.padding?.sides; const isAxialPadding = paddingSides && paddingSides.some(side => AXIAL_SIDES.includes(side)); const setPaddingValues = newPaddingValues => { const padding = filterValuesBySides(newPaddingValues, paddingSides); onChange((0, _object.setImmutably)(value, ['spacing', 'padding'], padding)); }; const hasPaddingValue = () => !!value?.spacing?.padding && Object.keys(value?.spacing?.padding).length; const resetPaddingValue = () => setPaddingValues(undefined); const onMouseOverPadding = () => onVisualize('padding'); // Margin const showMarginControl = useHasMargin(settings); const rawMargin = decodeValue(inheritedValue?.spacing?.margin); const marginValues = splitStyleValue(rawMargin); const marginSides = Array.isArray(settings?.spacing?.margin) ? settings?.spacing?.margin : settings?.spacing?.margin?.sides; const isAxialMargin = marginSides && marginSides.some(side => AXIAL_SIDES.includes(side)); const setMarginValues = newMarginValues => { const margin = filterValuesBySides(newMarginValues, marginSides); onChange((0, _object.setImmutably)(value, ['spacing', 'margin'], margin)); }; const hasMarginValue = () => !!value?.spacing?.margin && Object.keys(value?.spacing?.margin).length; const resetMarginValue = () => setMarginValues(undefined); const onMouseOverMargin = () => onVisualize('margin'); // Block Gap const showGapControl = useHasGap(settings); const gapSides = Array.isArray(settings?.spacing?.blockGap) ? settings?.spacing?.blockGap : settings?.spacing?.blockGap?.sides; const isAxialGap = gapSides && gapSides.some(side => AXIAL_SIDES.includes(side)); const gapValue = decodeValue(inheritedValue?.spacing?.blockGap); const gapValues = splitGapValue(gapValue, isAxialGap); const setGapValue = newGapValue => { onChange((0, _object.setImmutably)(value, ['spacing', 'blockGap'], newGapValue)); }; const setGapValues = nextBoxGapValue => { if (!nextBoxGapValue) { setGapValue(null); } // If axial gap is not enabled, treat the 'top' value as the shorthand gap value. if (!isAxialGap && nextBoxGapValue?.hasOwnProperty('top')) { setGapValue(nextBoxGapValue.top); } else { setGapValue({ top: nextBoxGapValue?.top, left: nextBoxGapValue?.left }); } }; const resetGapValue = () => setGapValue(undefined); const hasGapValue = () => !!value?.spacing?.blockGap; // Min Height const showMinHeightControl = useHasMinHeight(settings); const minHeightValue = decodeValue(inheritedValue?.dimensions?.minHeight); const setMinHeightValue = newValue => { const tempValue = (0, _object.setImmutably)(value, ['dimensions', 'minHeight'], newValue); // Apply min-height, while removing any applied aspect ratio. onChange((0, _object.setImmutably)(tempValue, ['dimensions', 'aspectRatio'], undefined)); }; const resetMinHeightValue = () => { setMinHeightValue(undefined); }; const hasMinHeightValue = () => !!value?.dimensions?.minHeight; // Aspect Ratio const showAspectRatioControl = useHasAspectRatio(settings); const aspectRatioValue = decodeValue(inheritedValue?.dimensions?.aspectRatio); const setAspectRatioValue = newValue => { const tempValue = (0, _object.setImmutably)(value, ['dimensions', 'aspectRatio'], newValue); // Apply aspect-ratio, while removing any applied min-height. onChange((0, _object.setImmutably)(tempValue, ['dimensions', 'minHeight'], undefined)); }; const hasAspectRatioValue = () => !!value?.dimensions?.aspectRatio; // Child Layout const showChildLayoutControl = useHasChildLayout(settings); const childLayout = inheritedValue?.layout; const setChildLayout = newChildLayout => { onChange({ ...value, layout: { ...newChildLayout } }); }; const resetAllFilter = (0, _element.useCallback)(previousValue => { return { ...previousValue, layout: (0, _utils2.cleanEmptyObject)({ ...previousValue?.layout, contentSize: undefined, wideSize: undefined, selfStretch: undefined, flexSize: undefined, columnStart: undefined, rowStart: undefined, columnSpan: undefined, rowSpan: undefined }), spacing: { ...previousValue?.spacing, padding: undefined, margin: undefined, blockGap: undefined }, dimensions: { ...previousValue?.dimensions, minHeight: undefined, aspectRatio: undefined } }; }, []); const onMouseLeaveControls = () => onVisualize(false); return /*#__PURE__*/(0, _jsxRuntime.jsxs)(Wrapper, { resetAllFilter: resetAllFilter, value: value, onChange: onChange, panelId: panelId, children: [(showContentSizeControl || showWideSizeControl) && /*#__PURE__*/(0, _jsxRuntime.jsx)("span", { className: "span-columns", children: (0, _i18n.__)('Set the width of the main content area.') }), showContentSizeControl && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanelItem, { label: (0, _i18n.__)('Content width'), hasValue: hasUserSetContentSizeValue, onDeselect: resetContentSizeValue, isShownByDefault: (_defaultControls$cont = defaultControls.contentSize) !== null && _defaultControls$cont !== void 0 ? _defaultControls$cont : DEFAULT_CONTROLS.contentSize, panelId: panelId, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalUnitControl, { __next40pxDefaultSize: true, label: (0, _i18n.__)('Content width'), labelPosition: "top", value: contentSizeValue || '', onChange: nextContentSize => { setContentSizeValue(nextContentSize); }, units: units, prefix: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalInputControlPrefixWrapper, { variant: "icon", children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.Icon, { icon: _icons.alignNone }) }) }) }), showWideSizeControl && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanelItem, { label: (0, _i18n.__)('Wide width'), hasValue: hasUserSetWideSizeValue, onDeselect: resetWideSizeValue, isShownByDefault: (_defaultControls$wide = defaultControls.wideSize) !== null && _defaultControls$wide !== void 0 ? _defaultControls$wide : DEFAULT_CONTROLS.wideSize, panelId: panelId, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalUnitControl, { __next40pxDefaultSize: true, label: (0, _i18n.__)('Wide width'), labelPosition: "top", value: wideSizeValue || '', onChange: nextWideSize => { setWideSizeValue(nextWideSize); }, units: units, prefix: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalInputControlPrefixWrapper, { variant: "icon", children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_icons.Icon, { icon: _icons.stretchWide }) }) }) }), showPaddingControl && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalToolsPanelItem, { hasValue: hasPaddingValue, label: (0, _i18n.__)('Padding'), onDeselect: resetPaddingValue, isShownByDefault: (_defaultControls$padd = defaultControls.padding) !== null && _defaultControls$padd !== void 0 ? _defaultControls$padd : DEFAULT_CONTROLS.padding, className: (0, _clsx.default)({ 'tools-panel-item-spacing': showSpacingPresetsControl }), panelId: panelId, children: [!showSpacingPresetsControl && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.BoxControl, { __next40pxDefaultSize: true, values: paddingValues, onChange: setPaddingValues, label: (0, _i18n.__)('Padding'), sides: paddingSides, units: units, allowReset: false, splitOnAxis: isAxialPadding, inputProps: { onMouseOver: onMouseOverPadding, onMouseOut: onMouseLeaveControls } }), showSpacingPresetsControl && /*#__PURE__*/(0, _jsxRuntime.jsx)(_spacingSizesControl.default, { values: paddingValues, onChange: setPaddingValues, label: (0, _i18n.__)('Padding'), sides: paddingSides, units: units, allowReset: false, onMouseOver: onMouseOverPadding, onMouseOut: onMouseLeaveControls })] }), showMarginControl && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalToolsPanelItem, { hasValue: hasMarginValue, label: (0, _i18n.__)('Margin'), onDeselect: resetMarginValue, isShownByDefault: (_defaultControls$marg = defaultControls.margin) !== null && _defaultControls$marg !== void 0 ? _defaultControls$marg : DEFAULT_CONTROLS.margin, className: (0, _clsx.default)({ 'tools-panel-item-spacing': showSpacingPresetsControl }), panelId: panelId, children: [!showSpacingPresetsControl && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.BoxControl, { __next40pxDefaultSize: true, values: marginValues, onChange: setMarginValues, inputProps: { min: minMarginValue, onDragStart: () => { // Reset to 0 in case the value was negative. setMinMarginValue(0); }, onDragEnd: () => { setMinMarginValue(minimumMargin); }, onMouseOver: onMouseOverMargin, onMouseOut: onMouseLeaveControls }, label: (0, _i18n.__)('Margin'), sides: marginSides, units: units, allowReset: false, splitOnAxis: isAxialMargin }), showSpacingPresetsControl && /*#__PURE__*/(0, _jsxRuntime.jsx)(_spacingSizesControl.default, { values: marginValues, onChange: setMarginValues, minimumCustomValue: -Infinity, label: (0, _i18n.__)('Margin'), sides: marginSides, units: units, allowReset: false, onMouseOver: onMouseOverMargin, onMouseOut: onMouseLeaveControls })] }), showGapControl && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.__experimentalToolsPanelItem, { hasValue: hasGapValue, label: (0, _i18n.__)('Block spacing'), onDeselect: resetGapValue, isShownByDefault: (_defaultControls$bloc = defaultControls.blockGap) !== null && _defaultControls$bloc !== void 0 ? _defaultControls$bloc : DEFAULT_CONTROLS.blockGap, className: (0, _clsx.default)({ 'tools-panel-item-spacing': showSpacingPresetsControl, 'single-column': // If UnitControl is used, should be single-column. !showSpacingPresetsControl && !isAxialGap }), panelId: panelId, children: [!showSpacingPresetsControl && (isAxialGap ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.BoxControl, { __next40pxDefaultSize: true, label: (0, _i18n.__)('Block spacing'), min: 0, onChange: setGapValues, units: units, sides: gapSides, values: gapValues, allowReset: false, splitOnAxis: isAxialGap }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalUnitControl, { __next40pxDefaultSize: true, label: (0, _i18n.__)('Block spacing'), min: 0, onChange: setGapValue, units: units, value: gapValue })), showSpacingPresetsControl && /*#__PURE__*/(0, _jsxRuntime.jsx)(_spacingSizesControl.default, { label: (0, _i18n.__)('Block spacing'), min: 0, onChange: setGapValues, showSideInLabel: false, sides: isAxialGap ? gapSides : ['top'] // Use 'top' as the shorthand property in non-axial configurations. , values: gapValues, allowReset: false })] }), showChildLayoutControl && /*#__PURE__*/(0, _jsxRuntime.jsx)(_childLayoutControl.default, { value: childLayout, onChange: setChildLayout, parentLayout: settings?.parentLayout, panelId: panelId, isShownByDefault: (_defaultControls$chil = defaultControls.childLayout) !== null && _defaultControls$chil !== void 0 ? _defaultControls$chil : DEFAULT_CONTROLS.childLayout }), showMinHeightControl && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalToolsPanelItem, { hasValue: hasMinHeightValue, label: (0, _i18n.__)('Minimum height'), onDeselect: resetMinHeightValue, isShownByDefault: (_defaultControls$minH = defaultControls.minHeight) !== null && _defaultControls$minH !== void 0 ? _defaultControls$minH : DEFAULT_CONTROLS.minHeight, panelId: panelId, children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_heightControl.default, { label: (0, _i18n.__)('Minimum height'), value: minHeightValue, onChange: setMinHeightValue }) }), showAspectRatioControl && /*#__PURE__*/(0, _jsxRuntime.jsx)(_aspectRatioTool.default, { hasValue: hasAspectRatioValue, value: aspectRatioValue, onChange: setAspectRatioValue, panelId: panelId, isShownByDefault: (_defaultControls$aspe = defaultControls.aspectRatio) !== null && _defaultControls$aspe !== void 0 ? _defaultControls$aspe : DEFAULT_CONTROLS.aspectRatio })] }); } //# sourceMappingURL=dimensions-panel.js.map