@wordpress/block-library
Version:
Block library for the WordPress editor.
310 lines (308 loc) • 9.7 kB
JavaScript
/**
* External dependencies
*/
import clsx from 'clsx';
/**
* WordPress dependencies
*/
import { useBlockProps, getCustomValueFromPreset, getSpacingPresetCssVar, store as blockEditorStore, privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';
import { ResizableBox } from '@wordpress/components';
import { useState, useEffect } from '@wordpress/element';
import { View } from '@wordpress/primitives';
import { useSelect, useDispatch } from '@wordpress/data';
/**
* Internal dependencies
*/
import { unlock } from '../lock-unlock';
import SpacerControls from './controls';
import { MIN_SPACER_SIZE } from './constants';
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
const {
useSpacingSizes
} = unlock(blockEditorPrivateApis);
const ResizableSpacer = ({
orientation,
onResizeStart,
onResize,
onResizeStop,
isSelected,
isResizing,
setIsResizing,
...props
}) => {
const getCurrentSize = elt => {
return orientation === 'horizontal' ? elt.clientWidth : elt.clientHeight;
};
const getNextVal = elt => {
return `${getCurrentSize(elt)}px`;
};
return /*#__PURE__*/_jsx(ResizableBox, {
className: clsx('block-library-spacer__resize-container', {
'resize-horizontal': orientation === 'horizontal',
'is-resizing': isResizing,
'is-selected': isSelected
}),
onResizeStart: (_event, _direction, elt) => {
const nextVal = getNextVal(elt);
onResizeStart(nextVal);
onResize(nextVal);
},
onResize: (_event, _direction, elt) => {
onResize(getNextVal(elt));
if (!isResizing) {
setIsResizing(true);
}
},
onResizeStop: (_event, _direction, elt) => {
const nextVal = getCurrentSize(elt);
onResizeStop(`${nextVal}px`);
setIsResizing(false);
},
__experimentalShowTooltip: true,
__experimentalTooltipProps: {
axis: orientation === 'horizontal' ? 'x' : 'y',
position: 'corner',
isVisible: isResizing
},
showHandle: isSelected,
...props
});
};
const SpacerEdit = ({
attributes,
isSelected,
setAttributes,
toggleSelection,
context,
__unstableParentLayout: parentLayout,
className
}) => {
const disableCustomSpacingSizes = useSelect(select => {
const editorSettings = select(blockEditorStore).getSettings();
return editorSettings?.disableCustomSpacingSizes;
});
const {
orientation
} = context;
const {
orientation: parentOrientation,
type,
default: {
type: defaultType
} = {}
} = parentLayout || {};
// Check if the spacer is inside a flex container.
const isFlexLayout = type === 'flex' || !type && defaultType === 'flex';
// If the spacer is inside a flex container, it should either inherit the orientation
// of the parent or use the flex default orientation.
const inheritedOrientation = !parentOrientation && isFlexLayout ? 'horizontal' : parentOrientation || orientation;
const {
height,
width,
style: blockStyle = {}
} = attributes;
const {
layout = {}
} = blockStyle;
const {
selfStretch,
flexSize
} = layout;
const spacingSizes = useSpacingSizes();
const [isResizing, setIsResizing] = useState(false);
const [temporaryHeight, setTemporaryHeight] = useState(null);
const [temporaryWidth, setTemporaryWidth] = useState(null);
const onResizeStart = () => toggleSelection(false);
const onResizeStop = () => toggleSelection(true);
const {
__unstableMarkNextChangeAsNotPersistent
} = useDispatch(blockEditorStore);
const handleOnVerticalResizeStop = newHeight => {
onResizeStop();
if (isFlexLayout) {
setAttributes({
style: {
...blockStyle,
layout: {
...layout,
flexSize: newHeight,
selfStretch: 'fixed'
}
}
});
}
setAttributes({
height: newHeight
});
setTemporaryHeight(null);
};
const handleOnHorizontalResizeStop = newWidth => {
onResizeStop();
if (isFlexLayout) {
setAttributes({
style: {
...blockStyle,
layout: {
...layout,
flexSize: newWidth,
selfStretch: 'fixed'
}
}
});
}
setAttributes({
width: newWidth
});
setTemporaryWidth(null);
};
const getHeightForVerticalBlocks = () => {
if (isFlexLayout) {
return undefined;
}
return temporaryHeight || getSpacingPresetCssVar(height) || undefined;
};
const getWidthForHorizontalBlocks = () => {
if (isFlexLayout) {
return undefined;
}
return temporaryWidth || getSpacingPresetCssVar(width) || undefined;
};
const sizeConditionalOnOrientation = inheritedOrientation === 'horizontal' ? temporaryWidth || flexSize : temporaryHeight || flexSize;
const style = {
height: inheritedOrientation === 'horizontal' ? 24 : getHeightForVerticalBlocks(),
width: inheritedOrientation === 'horizontal' ? getWidthForHorizontalBlocks() : undefined,
// In vertical flex containers, the spacer shrinks to nothing without a minimum width.
minWidth: inheritedOrientation === 'vertical' && isFlexLayout ? 48 : undefined,
// Add flex-basis so temporary sizes are respected.
flexBasis: isFlexLayout ? sizeConditionalOnOrientation : undefined,
// Remove flex-grow when resizing.
flexGrow: isFlexLayout && isResizing ? 0 : undefined
};
const resizableBoxWithOrientation = blockOrientation => {
if (blockOrientation === 'horizontal') {
return /*#__PURE__*/_jsx(ResizableSpacer, {
minWidth: MIN_SPACER_SIZE,
enable: {
top: false,
right: true,
bottom: false,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false
},
orientation: blockOrientation,
onResizeStart: onResizeStart,
onResize: setTemporaryWidth,
onResizeStop: handleOnHorizontalResizeStop,
isSelected: isSelected,
isResizing: isResizing,
setIsResizing: setIsResizing
});
}
return /*#__PURE__*/_jsx(_Fragment, {
children: /*#__PURE__*/_jsx(ResizableSpacer, {
minHeight: MIN_SPACER_SIZE,
enable: {
top: false,
right: false,
bottom: true,
left: false,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false
},
orientation: blockOrientation,
onResizeStart: onResizeStart,
onResize: setTemporaryHeight,
onResizeStop: handleOnVerticalResizeStop,
isSelected: isSelected,
isResizing: isResizing,
setIsResizing: setIsResizing
})
});
};
useEffect(() => {
// To avoid interfering with undo/redo operations any changes in this
// effect must not make history and should be preceded by
// `__unstableMarkNextChangeAsNotPersistent()`.
const setAttributesCovertly = nextAttributes => {
__unstableMarkNextChangeAsNotPersistent();
setAttributes(nextAttributes);
};
if (isFlexLayout && selfStretch !== 'fill' && selfStretch !== 'fit' && flexSize === undefined) {
if (inheritedOrientation === 'horizontal') {
// If spacer is moving from a vertical container to a horizontal container,
// it might not have width but have height instead.
const newSize = getCustomValueFromPreset(width, spacingSizes) || getCustomValueFromPreset(height, spacingSizes) || '100px';
setAttributesCovertly({
width: '0px',
style: {
...blockStyle,
layout: {
...layout,
flexSize: newSize,
selfStretch: 'fixed'
}
}
});
} else {
const newSize = getCustomValueFromPreset(height, spacingSizes) || getCustomValueFromPreset(width, spacingSizes) || '100px';
setAttributesCovertly({
height: '0px',
style: {
...blockStyle,
layout: {
...layout,
flexSize: newSize,
selfStretch: 'fixed'
}
}
});
}
} else if (isFlexLayout && (selfStretch === 'fill' || selfStretch === 'fit')) {
setAttributesCovertly(inheritedOrientation === 'horizontal' ? {
width: undefined
} : {
height: undefined
});
} else if (!isFlexLayout && (selfStretch || flexSize)) {
setAttributesCovertly({
...(inheritedOrientation === 'horizontal' ? {
width: flexSize
} : {
height: flexSize
}),
style: {
...blockStyle,
layout: {
...layout,
flexSize: undefined,
selfStretch: undefined
}
}
});
}
}, [blockStyle, flexSize, height, inheritedOrientation, isFlexLayout, layout, selfStretch, setAttributes, spacingSizes, width, __unstableMarkNextChangeAsNotPersistent]);
return /*#__PURE__*/_jsxs(_Fragment, {
children: [/*#__PURE__*/_jsx(View, {
...useBlockProps({
style,
className: clsx(className, {
'custom-sizes-disabled': disableCustomSpacingSizes
})
}),
children: resizableBoxWithOrientation(inheritedOrientation)
}), !isFlexLayout && /*#__PURE__*/_jsx(SpacerControls, {
setAttributes: setAttributes,
height: temporaryHeight || height,
width: temporaryWidth || width,
orientation: inheritedOrientation,
isResizing: isResizing
})]
});
};
export default SpacerEdit;
//# sourceMappingURL=edit.js.map