@wordpress/block-editor
Version:
205 lines (185 loc) • 6.73 kB
JavaScript
/**
* WordPress dependencies
*/
import { useState } from '@wordpress/element';
/**
* Internal dependencies
*/
import AspectRatioTool from './aspect-ratio-tool';
import ScaleTool from './scale-tool';
import WidthHeightTool from './width-height-tool';
/**
* @typedef {import('@wordpress/components/build-types/select-control/types').SelectControlProps} SelectControlProps
*/
/**
* @typedef {import('@wordpress/components/build-types/unit-control/types').WPUnitControlUnit} WPUnitControlUnit
*/
/**
* @typedef {Object} Dimensions
* @property {string} [width] CSS width property.
* @property {string} [height] CSS height property.
* @property {string} [scale] CSS object-fit property.
* @property {string} [aspectRatio] CSS aspect-ratio property.
*/
/**
* @callback DimensionsControlsOnChange
* @param {Dimensions} nextValue
* @return {void}
*/
/**
* @typedef {Object} DimensionsControlsProps
* @property {string} [panelId] ID of the panel that contains the controls.
* @property {Dimensions} [value] Current dimensions values.
* @property {DimensionsControlsOnChange} [onChange] Callback to update the dimensions values.
* @property {SelectControlProps[]} [aspectRatioOptions] Aspect ratio options.
* @property {SelectControlProps[]} [scaleOptions] Scale options.
* @property {WPUnitControlUnit[]} [unitsOptions] Units options.
*/
/**
* Component that renders controls to edit the dimensions of an image or container.
*
* @param {DimensionsControlsProps} props The component props.
*
* @return {Element} The dimensions controls.
*/
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
function DimensionsTool({
panelId,
value = {},
onChange = () => {},
aspectRatioOptions,
// Default options handled by AspectRatioTool.
defaultAspectRatio = 'auto',
// Match CSS default value for aspect-ratio.
scaleOptions,
// Default options handled by ScaleTool.
defaultScale = 'fill',
// Match CSS default value for object-fit.
unitsOptions,
// Default options handled by UnitControl.
tools = ['aspectRatio', 'widthHeight', 'scale']
}) {
// Coerce undefined and CSS default values to be null.
const width = value.width === undefined || value.width === 'auto' ? null : value.width;
const height = value.height === undefined || value.height === 'auto' ? null : value.height;
const aspectRatio = value.aspectRatio === undefined || value.aspectRatio === 'auto' ? null : value.aspectRatio;
const scale = value.scale === undefined || value.scale === 'fill' ? null : value.scale;
// Keep track of state internally, so when the value is cleared by means
// other than directly editing that field, it's easier to restore the
// previous value.
const [lastScale, setLastScale] = useState(scale);
const [lastAspectRatio, setLastAspectRatio] = useState(aspectRatio);
// 'custom' is not a valid value for CSS aspect-ratio, but it is used in the
// dropdown to indicate that setting both the width and height is the same
// as a custom aspect ratio.
const aspectRatioValue = width && height ? 'custom' : lastAspectRatio;
const showScaleControl = aspectRatio || width && height;
return /*#__PURE__*/_jsxs(_Fragment, {
children: [tools.includes('aspectRatio') && /*#__PURE__*/_jsx(AspectRatioTool, {
panelId: panelId,
options: aspectRatioOptions,
defaultValue: defaultAspectRatio,
value: aspectRatioValue,
onChange: nextAspectRatio => {
const nextValue = {
...value
};
// 'auto' is CSS default, so it gets treated as null.
nextAspectRatio = nextAspectRatio === 'auto' ? null : nextAspectRatio;
setLastAspectRatio(nextAspectRatio);
// Update aspectRatio.
if (!nextAspectRatio) {
delete nextValue.aspectRatio;
} else {
nextValue.aspectRatio = nextAspectRatio;
}
// Auto-update scale.
if (!nextAspectRatio) {
delete nextValue.scale;
} else if (lastScale) {
nextValue.scale = lastScale;
} else {
nextValue.scale = defaultScale;
setLastScale(defaultScale);
}
// Auto-update width and height.
if ('custom' !== nextAspectRatio && width && height) {
delete nextValue.height;
}
onChange(nextValue);
}
}), tools.includes('widthHeight') && /*#__PURE__*/_jsx(WidthHeightTool, {
panelId: panelId,
units: unitsOptions,
value: {
width,
height
},
onChange: ({
width: nextWidth,
height: nextHeight
}) => {
const nextValue = {
...value
};
// 'auto' is CSS default, so it gets treated as null.
nextWidth = nextWidth === 'auto' ? null : nextWidth;
nextHeight = nextHeight === 'auto' ? null : nextHeight;
// Update width.
if (!nextWidth) {
delete nextValue.width;
} else {
nextValue.width = nextWidth;
}
// Update height.
if (!nextHeight) {
delete nextValue.height;
} else {
nextValue.height = nextHeight;
}
// Auto-update aspectRatio.
if (nextWidth && nextHeight) {
delete nextValue.aspectRatio;
} else if (lastAspectRatio) {
nextValue.aspectRatio = lastAspectRatio;
} else {
// No setting defaultAspectRatio here, because
// aspectRatio is optional in this scenario,
// unlike scale.
}
// Auto-update scale.
if (!lastAspectRatio && !!nextWidth !== !!nextHeight) {
delete nextValue.scale;
} else if (lastScale) {
nextValue.scale = lastScale;
} else {
nextValue.scale = defaultScale;
setLastScale(defaultScale);
}
onChange(nextValue);
}
}), tools.includes('scale') && showScaleControl && /*#__PURE__*/_jsx(ScaleTool, {
panelId: panelId,
options: scaleOptions,
defaultValue: defaultScale,
value: lastScale,
onChange: nextScale => {
const nextValue = {
...value
};
// 'fill' is CSS default, so it gets treated as null.
nextScale = nextScale === 'fill' ? null : nextScale;
setLastScale(nextScale);
// Update scale.
if (!nextScale) {
delete nextValue.scale;
} else {
nextValue.scale = nextScale;
}
onChange(nextValue);
}
})]
});
}
export default DimensionsTool;
//# sourceMappingURL=index.js.map