@wordpress/block-library
Version:
Block library for the WordPress editor.
325 lines (305 loc) • 10.6 kB
JavaScript
import _extends from "@babel/runtime/helpers/esm/extends";
import { createElement, Fragment } from "@wordpress/element";
/**
* External dependencies
*/
import classnames from 'classnames';
import { extend } from 'colord';
import namesPlugin from 'colord/plugins/names';
/**
* WordPress dependencies
*/
import { useEntityProp, store as coreStore } from '@wordpress/core-data';
import { useEffect, useRef } from '@wordpress/element';
import { Placeholder, Spinner } from '@wordpress/components';
import { compose } from '@wordpress/compose';
import { withColors, ColorPalette, useBlockProps, useSetting, useInnerBlocksProps, __experimentalUseGradient, store as blockEditorStore } from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
import { useSelect, useDispatch } from '@wordpress/data';
import { isBlobURL } from '@wordpress/blob';
import { store as noticesStore } from '@wordpress/notices';
/**
* Internal dependencies
*/
import { attributesFromMedia, IMAGE_BACKGROUND_TYPE, VIDEO_BACKGROUND_TYPE, dimRatioToClass, isContentPositionCenter, getPositionClassName, mediaPosition } from '../shared';
import useCoverIsDark from './use-cover-is-dark';
import CoverInspectorControls from './inspector-controls';
import CoverBlockControls from './block-controls';
import CoverPlaceholder from './cover-placeholder';
import ResizableCover from './resizable-cover';
extend([namesPlugin]);
function getInnerBlocksTemplate(attributes) {
return [['core/paragraph', {
align: 'center',
placeholder: __('Write title…'),
...attributes
}]];
}
/**
* Is the URL a temporary blob URL? A blob URL is one that is used temporarily while
* the media (image or video) is being uploaded and will not have an id allocated yet.
*
* @param {number} id The id of the media.
* @param {string} url The url of the media.
*
* @return {boolean} Is the URL a Blob URL.
*/
const isTemporaryMedia = (id, url) => !id && isBlobURL(url);
function CoverEdit(_ref) {
var _useSetting;
let {
attributes,
clientId,
isSelected,
overlayColor,
setAttributes,
setOverlayColor,
toggleSelection,
context: {
postId,
postType
}
} = _ref;
const {
contentPosition,
id,
useFeaturedImage,
dimRatio,
focalPoint,
hasParallax,
isDark,
isRepeated,
minHeight,
minHeightUnit,
alt,
allowedBlocks,
templateLock
} = attributes;
const [featuredImage] = useEntityProp('postType', postType, 'featured_media', postId);
const media = useSelect(select => featuredImage && select(coreStore).getMedia(featuredImage, {
context: 'view'
}), [featuredImage]);
const mediaUrl = media === null || media === void 0 ? void 0 : media.source_url; // instead of destructuring the attributes
// we define the url and background type
// depending on the value of the useFeaturedImage flag
// to preview in edit the dynamic featured image
const url = useFeaturedImage ? mediaUrl : attributes.url;
const backgroundType = useFeaturedImage ? IMAGE_BACKGROUND_TYPE : attributes.backgroundType;
const {
__unstableMarkNextChangeAsNotPersistent
} = useDispatch(blockEditorStore);
const {
createErrorNotice
} = useDispatch(noticesStore);
const {
gradientClass,
gradientValue
} = __experimentalUseGradient();
const onSelectMedia = attributesFromMedia(setAttributes, dimRatio);
const isUploadingMedia = isTemporaryMedia(id, url);
const onUploadError = message => {
createErrorNotice(message, {
type: 'snackbar'
});
};
const mediaElement = useRef();
const isCoverDark = useCoverIsDark(url, dimRatio, overlayColor.color, mediaElement);
useEffect(() => {
// This side-effect should not create an undo level.
__unstableMarkNextChangeAsNotPersistent();
setAttributes({
isDark: isCoverDark
});
}, [isCoverDark]);
const isImageBackground = IMAGE_BACKGROUND_TYPE === backgroundType;
const isVideoBackground = VIDEO_BACKGROUND_TYPE === backgroundType;
const minHeightWithUnit = minHeight && minHeightUnit ? `${minHeight}${minHeightUnit}` : minHeight;
const isImgElement = !(hasParallax || isRepeated);
const style = {
minHeight: minHeightWithUnit || undefined
};
const backgroundImage = url ? `url(${url})` : undefined;
const backgroundPosition = mediaPosition(focalPoint);
const bgStyle = {
backgroundColor: overlayColor.color
};
const mediaStyle = {
objectPosition: focalPoint && isImgElement ? mediaPosition(focalPoint) : undefined
};
const hasBackground = !!(url || overlayColor.color || gradientValue);
const hasInnerBlocks = useSelect(select => select(blockEditorStore).getBlock(clientId).innerBlocks.length > 0, [clientId]);
const ref = useRef();
const blockProps = useBlockProps({
ref
}); // Check for fontSize support before we pass a fontSize attribute to the innerBlocks.
const hasFontSizes = !!((_useSetting = useSetting('typography.fontSizes')) !== null && _useSetting !== void 0 && _useSetting.length);
const innerBlocksTemplate = getInnerBlocksTemplate({
fontSize: hasFontSizes ? 'large' : undefined
});
const innerBlocksProps = useInnerBlocksProps({
className: 'wp-block-cover__inner-container'
}, {
template: innerBlocksTemplate,
templateInsertUpdatesSelection: true,
allowedBlocks,
templateLock
});
const currentSettings = {
isVideoBackground,
isImageBackground,
mediaElement,
hasInnerBlocks,
url,
isImgElement,
overlayColor
};
const toggleUseFeaturedImage = () => {
setAttributes({
id: undefined,
url: undefined,
useFeaturedImage: !useFeaturedImage,
dimRatio: dimRatio === 100 ? 50 : dimRatio,
backgroundType: useFeaturedImage ? IMAGE_BACKGROUND_TYPE : undefined
});
};
const blockControls = createElement(CoverBlockControls, {
attributes: attributes,
setAttributes: setAttributes,
onSelectMedia: onSelectMedia,
currentSettings: currentSettings,
toggleUseFeaturedImage: toggleUseFeaturedImage
});
const inspectorControls = createElement(CoverInspectorControls, {
attributes: attributes,
setAttributes: setAttributes,
clientId: clientId,
setOverlayColor: setOverlayColor,
coverRef: ref,
currentSettings: currentSettings,
toggleUseFeaturedImage: toggleUseFeaturedImage
});
if (!useFeaturedImage && !hasInnerBlocks && !hasBackground) {
return createElement(Fragment, null, blockControls, inspectorControls, createElement("div", _extends({}, blockProps, {
className: classnames('is-placeholder', blockProps.className)
}), createElement(CoverPlaceholder, {
onSelectMedia: onSelectMedia,
onError: onUploadError,
style: {
minHeight: minHeightWithUnit || undefined
},
toggleUseFeaturedImage: toggleUseFeaturedImage
}, createElement("div", {
className: "wp-block-cover__placeholder-background-options"
}, createElement(ColorPalette, {
disableCustomColors: true,
value: overlayColor.color,
onChange: setOverlayColor,
clearable: false
}))), createElement(ResizableCover, {
className: "block-library-cover__resize-container",
onResizeStart: () => {
setAttributes({
minHeightUnit: 'px'
});
toggleSelection(false);
},
onResize: value => {
setAttributes({
minHeight: value
});
},
onResizeStop: newMinHeight => {
toggleSelection(true);
setAttributes({
minHeight: newMinHeight
});
},
showHandle: isSelected
})));
}
const classes = classnames({
'is-dark-theme': isDark,
'is-light': !isDark,
'is-transient': isUploadingMedia,
'has-parallax': hasParallax,
'is-repeated': isRepeated,
'has-custom-content-position': !isContentPositionCenter(contentPosition)
}, getPositionClassName(contentPosition));
return createElement(Fragment, null, blockControls, inspectorControls, createElement("div", _extends({}, blockProps, {
className: classnames(classes, blockProps.className),
style: { ...style,
...blockProps.style
},
"data-url": url
}), createElement(ResizableCover, {
className: "block-library-cover__resize-container",
onResizeStart: () => {
setAttributes({
minHeightUnit: 'px'
});
toggleSelection(false);
},
onResize: value => {
setAttributes({
minHeight: value
});
},
onResizeStop: newMinHeight => {
toggleSelection(true);
setAttributes({
minHeight: newMinHeight
});
},
showHandle: isSelected
}), (!useFeaturedImage || url) && createElement("span", {
"aria-hidden": "true",
className: classnames('wp-block-cover__background', dimRatioToClass(dimRatio), {
[overlayColor.class]: overlayColor.class,
'has-background-dim': dimRatio !== undefined,
// For backwards compatibility. Former versions of the Cover Block applied
// `.wp-block-cover__gradient-background` in the presence of
// media, a gradient and a dim.
'wp-block-cover__gradient-background': url && gradientValue && dimRatio !== 0,
'has-background-gradient': gradientValue,
[gradientClass]: gradientClass
}),
style: {
backgroundImage: gradientValue,
...bgStyle
}
}), !url && useFeaturedImage && createElement(Placeholder, {
className: "wp-block-cover__image--placeholder-image",
withIllustration: true
}), url && isImageBackground && (isImgElement ? createElement("img", {
ref: mediaElement,
className: "wp-block-cover__image-background",
alt: alt,
src: url,
style: mediaStyle
}) : createElement("div", {
ref: mediaElement,
role: "img",
className: classnames(classes, 'wp-block-cover__image-background'),
style: {
backgroundImage,
backgroundPosition
}
})), url && isVideoBackground && createElement("video", {
ref: mediaElement,
className: "wp-block-cover__video-background",
autoPlay: true,
muted: true,
loop: true,
src: url,
style: mediaStyle
}), isUploadingMedia && createElement(Spinner, null), createElement(CoverPlaceholder, {
disableMediaButtons: true,
onSelectMedia: onSelectMedia,
onError: onUploadError,
toggleUseFeaturedImage: toggleUseFeaturedImage
}), createElement("div", innerBlocksProps)));
}
export default compose([withColors({
overlayColor: 'background-color'
})])(CoverEdit);
//# sourceMappingURL=index.js.map