UNPKG

@wordpress/block-library

Version:
588 lines (586 loc) 21.8 kB
"use strict"; var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // packages/block-library/src/cover/edit/index.js var edit_exports = {}; __export(edit_exports, { default: () => edit_default }); module.exports = __toCommonJS(edit_exports); var import_clsx = __toESM(require("clsx")); var import_core_data = require("@wordpress/core-data"); var import_element = require("@wordpress/element"); var import_components = require("@wordpress/components"); var import_compose = require("@wordpress/compose"); var import_block_editor = require("@wordpress/block-editor"); var import_i18n = require("@wordpress/i18n"); var import_data = require("@wordpress/data"); var import_blob = require("@wordpress/blob"); var import_notices = require("@wordpress/notices"); var import_shared = require("../shared"); var import_inspector_controls = __toESM(require("./inspector-controls")); var import_block_controls = __toESM(require("./block-controls")); var import_cover_placeholder = __toESM(require("./cover-placeholder")); var import_resizable_cover_popover = __toESM(require("./resizable-cover-popover")); var import_color_utils = require("./color-utils"); var import_constants = require("../constants"); var import_embed_video_utils = require("../embed-video-utils"); var import_jsx_runtime = require("react/jsx-runtime"); function getInnerBlocksTemplate(attributes) { return [ [ "core/paragraph", { align: "center", placeholder: (0, import_i18n.__)("Write title\u2026"), ...attributes } ] ]; } var isTemporaryMedia = (id, url) => !id && (0, import_blob.isBlobURL)(url); function CoverEdit({ attributes, clientId, isSelected, overlayColor, setAttributes, setOverlayColor, toggleSelection, context: { postId, postType } }) { const { contentPosition, id, url: originalUrl, backgroundType: originalBackgroundType, useFeaturedImage, dimRatio, focalPoint, hasParallax, isDark, isRepeated, minHeight, minHeightUnit, alt, allowedBlocks, templateLock, tagName: TagName = "div", isUserOverlayColor, sizeSlug, poster } = attributes; const [featuredImage] = (0, import_core_data.useEntityProp)( "postType", postType, "featured_media", postId ); const { getSettings } = (0, import_data.useSelect)(import_block_editor.store); const { __unstableMarkNextChangeAsNotPersistent } = (0, import_data.useDispatch)(import_block_editor.store); const { media } = (0, import_data.useSelect)( (select) => { return { media: featuredImage && useFeaturedImage ? select(import_core_data.store).getEntityRecord( "postType", "attachment", featuredImage, { context: "view" } ) : void 0 }; }, [featuredImage, useFeaturedImage] ); const mediaUrl = media?.media_details?.sizes?.[sizeSlug]?.source_url ?? media?.source_url; (0, import_element.useEffect)(() => { (async () => { if (!useFeaturedImage) { return; } const averageBackgroundColor = await (0, import_color_utils.getMediaColor)(mediaUrl); let newOverlayColor = overlayColor.color; if (!isUserOverlayColor) { newOverlayColor = averageBackgroundColor; __unstableMarkNextChangeAsNotPersistent(); setOverlayColor(newOverlayColor); } const newIsDark = (0, import_color_utils.compositeIsDark)( dimRatio, newOverlayColor, averageBackgroundColor ); __unstableMarkNextChangeAsNotPersistent(); setAttributes({ isDark: newIsDark, isUserOverlayColor: isUserOverlayColor || false }); })(); }, [mediaUrl]); const url = useFeaturedImage ? mediaUrl : ( // Ensure the url is not malformed due to sanitization through `wp_kses`. originalUrl?.replaceAll("&", "&") ); const backgroundType = useFeaturedImage ? import_shared.IMAGE_BACKGROUND_TYPE : originalBackgroundType; const { createErrorNotice } = (0, import_data.useDispatch)(import_notices.store); const { gradientClass, gradientValue } = (0, import_block_editor.__experimentalUseGradient)(); const onSelectMedia = async (newMedia) => { const mediaAttributes = (0, import_shared.attributesFromMedia)(newMedia); const isImage = [newMedia?.type, newMedia?.media_type].includes( import_shared.IMAGE_BACKGROUND_TYPE ); const averageBackgroundColor = await (0, import_color_utils.getMediaColor)( isImage ? newMedia?.url : void 0 ); let newOverlayColor = overlayColor.color; if (!isUserOverlayColor) { newOverlayColor = averageBackgroundColor; setOverlayColor(newOverlayColor); __unstableMarkNextChangeAsNotPersistent(); } const newDimRatio = originalUrl === void 0 && dimRatio === 100 ? 50 : dimRatio; const newIsDark = (0, import_color_utils.compositeIsDark)( newDimRatio, newOverlayColor, averageBackgroundColor ); if (backgroundType === import_shared.IMAGE_BACKGROUND_TYPE && mediaAttributes?.id) { const { imageDefaultSize } = getSettings(); if (sizeSlug && (newMedia?.sizes?.[sizeSlug] || newMedia?.media_details?.sizes?.[sizeSlug])) { mediaAttributes.sizeSlug = sizeSlug; mediaAttributes.url = newMedia?.sizes?.[sizeSlug]?.url || newMedia?.media_details?.sizes?.[sizeSlug]?.source_url; } else if (newMedia?.sizes?.[imageDefaultSize] || newMedia?.media_details?.sizes?.[imageDefaultSize]) { mediaAttributes.sizeSlug = imageDefaultSize; mediaAttributes.url = newMedia?.sizes?.[imageDefaultSize]?.url || newMedia?.media_details?.sizes?.[imageDefaultSize]?.source_url; } else { mediaAttributes.sizeSlug = import_constants.DEFAULT_MEDIA_SIZE_SLUG; } } setAttributes({ ...mediaAttributes, focalPoint: void 0, useFeaturedImage: void 0, dimRatio: newDimRatio, isDark: newIsDark, isUserOverlayColor: isUserOverlayColor || false }); }; const onClearMedia = () => { let newOverlayColor = overlayColor.color; if (!isUserOverlayColor) { newOverlayColor = import_color_utils.DEFAULT_OVERLAY_COLOR; setOverlayColor(void 0); __unstableMarkNextChangeAsNotPersistent(); } const newIsDark = (0, import_color_utils.compositeIsDark)( dimRatio, newOverlayColor, import_color_utils.DEFAULT_BACKGROUND_COLOR ); setAttributes({ url: void 0, id: void 0, backgroundType: void 0, focalPoint: void 0, hasParallax: void 0, isRepeated: void 0, useFeaturedImage: void 0, isDark: newIsDark }); }; const onSetOverlayColor = async (newOverlayColor) => { const averageBackgroundColor = await (0, import_color_utils.getMediaColor)(url); const newIsDark = (0, import_color_utils.compositeIsDark)( dimRatio, newOverlayColor, averageBackgroundColor ); setOverlayColor(newOverlayColor); __unstableMarkNextChangeAsNotPersistent(); setAttributes({ isUserOverlayColor: true, isDark: newIsDark }); }; const onUpdateDimRatio = async (newDimRatio) => { const averageBackgroundColor = await (0, import_color_utils.getMediaColor)(url); const newIsDark = (0, import_color_utils.compositeIsDark)( newDimRatio, overlayColor.color, averageBackgroundColor ); setAttributes({ dimRatio: newDimRatio, isDark: newIsDark }); }; const onUploadError = (message) => { createErrorNotice(message, { type: "snackbar" }); }; const onSelectEmbedUrl = (embedUrl) => { const newDimRatio = originalUrl === void 0 && dimRatio === 100 ? 50 : dimRatio; setAttributes({ url: embedUrl, backgroundType: import_shared.EMBED_VIDEO_BACKGROUND_TYPE, dimRatio: newDimRatio, id: void 0, focalPoint: void 0, hasParallax: void 0, isRepeated: void 0, useFeaturedImage: void 0 }); }; const { embedPreview, isFetchingEmbed } = (0, import_data.useSelect)( (select) => { if (backgroundType !== import_shared.EMBED_VIDEO_BACKGROUND_TYPE || !url) { return { embedPreview: void 0, isFetchingEmbed: false }; } const { getEmbedPreview, isRequestingEmbedPreview } = select(import_core_data.store); return { embedPreview: getEmbedPreview(url), isFetchingEmbed: isRequestingEmbedPreview(url) }; }, [url, backgroundType] ); const embedSrc = (0, import_element.useMemo)(() => { if (backgroundType !== import_shared.EMBED_VIDEO_BACKGROUND_TYPE || !embedPreview?.html) { return null; } const iframeSrc = (0, import_embed_video_utils.getIframeSrc)(embedPreview.html); if (!iframeSrc) { return null; } return (0, import_embed_video_utils.getBackgroundVideoSrc)(iframeSrc); }, [embedPreview, backgroundType]); const isUploadingMedia = isTemporaryMedia(id, url); const isImageBackground = import_shared.IMAGE_BACKGROUND_TYPE === backgroundType; const isVideoBackground = import_shared.VIDEO_BACKGROUND_TYPE === backgroundType; const isEmbedVideoBackground = import_shared.EMBED_VIDEO_BACKGROUND_TYPE === backgroundType; const blockEditingMode = (0, import_block_editor.useBlockEditingMode)(); const hasNonContentControls = blockEditingMode === "default"; const [resizeListener, { height, width }] = (0, import_compose.useResizeObserver)(); const resizableBoxDimensions = (0, import_element.useMemo)(() => { return { height: minHeightUnit === "px" && minHeight ? minHeight : "auto", width: "auto" }; }, [minHeight, minHeightUnit]); const minHeightWithUnit = minHeight && minHeightUnit ? `${minHeight}${minHeightUnit}` : minHeight; const isImgElement = !(hasParallax || isRepeated); const style = { minHeight: minHeightWithUnit || void 0 }; const backgroundImage = url ? `url(${url})` : void 0; const backgroundPosition = (0, import_shared.mediaPosition)(focalPoint); const bgStyle = { backgroundColor: overlayColor.color }; const mediaStyle = { objectPosition: focalPoint && isImgElement ? (0, import_shared.mediaPosition)(focalPoint) : void 0 }; const hasBackground = !!(url || overlayColor.color || gradientValue); const hasInnerBlocks = (0, import_data.useSelect)( (select) => select(import_block_editor.store).getBlock(clientId).innerBlocks.length > 0, [clientId] ); const ref = (0, import_element.useRef)(); const blockProps = (0, import_block_editor.useBlockProps)({ ref }); const [fontSizes] = (0, import_block_editor.useSettings)("typography.fontSizes"); const hasFontSizes = fontSizes?.length > 0; const innerBlocksTemplate = getInnerBlocksTemplate({ fontSize: hasFontSizes ? "large" : void 0 }); const innerBlocksProps = (0, import_block_editor.useInnerBlocksProps)( { className: "wp-block-cover__inner-container" }, { // Avoid template sync when the `templateLock` value is `all` or `contentOnly`. // See: https://github.com/WordPress/gutenberg/pull/45632 template: !hasInnerBlocks ? innerBlocksTemplate : void 0, templateInsertUpdatesSelection: true, allowedBlocks, templateLock, dropZoneElement: ref.current } ); const mediaElement = (0, import_element.useRef)(); const currentSettings = { isVideoBackground, isImageBackground, mediaElement, hasInnerBlocks, url, isImgElement, overlayColor }; const toggleUseFeaturedImage = async () => { const newUseFeaturedImage = !useFeaturedImage; const averageBackgroundColor = newUseFeaturedImage ? await (0, import_color_utils.getMediaColor)(mediaUrl) : import_color_utils.DEFAULT_BACKGROUND_COLOR; const newOverlayColor = !isUserOverlayColor ? averageBackgroundColor : overlayColor.color; if (!isUserOverlayColor) { if (newUseFeaturedImage) { setOverlayColor(newOverlayColor); } else { setOverlayColor(void 0); } __unstableMarkNextChangeAsNotPersistent(); } const newDimRatio = dimRatio === 100 ? 50 : dimRatio; const newIsDark = (0, import_color_utils.compositeIsDark)( newDimRatio, newOverlayColor, averageBackgroundColor ); setAttributes({ id: void 0, url: void 0, useFeaturedImage: newUseFeaturedImage, dimRatio: newDimRatio, backgroundType: useFeaturedImage ? import_shared.IMAGE_BACKGROUND_TYPE : void 0, isDark: newIsDark }); }; const blockControls = /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_block_controls.default, { attributes, setAttributes, onSelectMedia, onSelectEmbedUrl, currentSettings, toggleUseFeaturedImage, onClearMedia, blockEditingMode } ); const inspectorControls = /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_inspector_controls.default, { attributes, setAttributes, clientId, setOverlayColor: onSetOverlayColor, coverRef: ref, currentSettings, toggleUseFeaturedImage, updateDimRatio: onUpdateDimRatio, onClearMedia, featuredImage: media } ); const resizableCoverProps = { className: "block-library-cover__resize-container", clientId, height, minHeight: minHeightWithUnit, onResizeStart: () => { setAttributes({ minHeightUnit: "px" }); toggleSelection(false); }, onResize: (value) => { setAttributes({ minHeight: value }); }, onResizeStop: (newMinHeight) => { toggleSelection(true); setAttributes({ minHeight: newMinHeight }); }, // Hide the resize handle if an aspect ratio is set, as the aspect ratio takes precedence. showHandle: !attributes.style?.dimensions?.aspectRatio, size: resizableBoxDimensions, width }; if (!useFeaturedImage && !hasInnerBlocks && !hasBackground) { return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ blockControls, inspectorControls, hasNonContentControls && isSelected && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_resizable_cover_popover.default, { ...resizableCoverProps }), /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( TagName, { ...blockProps, className: (0, import_clsx.default)("is-placeholder", blockProps.className), style: { ...blockProps.style, minHeight: minHeightWithUnit || void 0 }, children: [ resizeListener, /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_cover_placeholder.default, { onSelectMedia, onError: onUploadError, toggleUseFeaturedImage, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "wp-block-cover__placeholder-background-options", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_block_editor.ColorPalette, { disableCustomColors: true, value: overlayColor.color, onChange: onSetOverlayColor, clearable: false, asButtons: true, "aria-label": (0, import_i18n.__)("Overlay color") } ) }) } ) ] } ) ] }); } const classes = (0, import_clsx.default)( { "is-dark-theme": isDark, "is-light": !isDark, "is-transient": isUploadingMedia, "has-parallax": hasParallax, "is-repeated": isRepeated, "has-custom-content-position": !(0, import_shared.isContentPositionCenter)(contentPosition) }, (0, import_shared.getPositionClassName)(contentPosition) ); const showOverlay = url || !useFeaturedImage || useFeaturedImage && !url; return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [ blockControls, inspectorControls, /* @__PURE__ */ (0, import_jsx_runtime.jsxs)( TagName, { ...blockProps, className: (0, import_clsx.default)(classes, blockProps.className), style: { ...style, ...blockProps.style }, "data-url": url, children: [ resizeListener, !url && useFeaturedImage && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_components.Placeholder, { className: "wp-block-cover__image--placeholder-image", withIllustration: true } ), url && isImageBackground && (isImgElement ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "img", { ref: mediaElement, className: "wp-block-cover__image-background", alt, src: url, style: mediaStyle } ) : /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { ref: mediaElement, role: alt ? "img" : void 0, "aria-label": alt ? alt : void 0, className: (0, import_clsx.default)( classes, "wp-block-cover__image-background" ), style: { backgroundImage, backgroundPosition } } )), url && isVideoBackground && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "video", { ref: mediaElement, className: "wp-block-cover__video-background", autoPlay: true, muted: true, loop: true, src: url, poster, style: mediaStyle } ), isEmbedVideoBackground && embedSrc && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "div", { ref: mediaElement, className: "wp-block-cover__video-background wp-block-cover__embed-background", style: mediaStyle, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "iframe", { src: embedSrc, title: "Background video", frameBorder: "0", allow: "autoplay; fullscreen" } ) } ), isEmbedVideoBackground && !embedSrc && isFetchingEmbed && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Spinner, {}), showOverlay && /* @__PURE__ */ (0, import_jsx_runtime.jsx)( "span", { "aria-hidden": "true", className: (0, import_clsx.default)( "wp-block-cover__background", (0, import_shared.dimRatioToClass)(dimRatio), { [overlayColor.class]: overlayColor.class, "has-background-dim": dimRatio !== void 0, // 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 } } ), isUploadingMedia && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Spinner, {}), /* @__PURE__ */ (0, import_jsx_runtime.jsx)( import_cover_placeholder.default, { disableMediaButtons: true, onSelectMedia, onError: onUploadError, toggleUseFeaturedImage } ), /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { ...innerBlocksProps }) ] } ), hasNonContentControls && isSelected && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_resizable_cover_popover.default, { ...resizableCoverProps }) ] }); } var edit_default = (0, import_compose.compose)([ (0, import_block_editor.withColors)({ overlayColor: "background-color" }) ])(CoverEdit); //# sourceMappingURL=index.js.map