UNPKG

@wordpress/block-library

Version:
410 lines (409 loc) 12.6 kB
import { Fragment, jsx, jsxs } from "react/jsx-runtime"; import clsx from "clsx"; import { isBlobURL } from "@wordpress/blob"; import { useEntityProp, store as coreStore } from "@wordpress/core-data"; import { useSelect, useDispatch } from "@wordpress/data"; import { ToggleControl, Placeholder, Button, Spinner, TextControl, ExternalLink, __experimentalToolsPanel as ToolsPanel, __experimentalToolsPanelItem as ToolsPanelItem } from "@wordpress/components"; import { InspectorControls, BlockControls, MediaPlaceholder, MediaReplaceFlow, useBlockProps, __experimentalUseBorderProps as useBorderProps, __experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles, useBlockEditingMode, privateApis as blockEditorPrivateApis, store as blockEditorStore } from "@wordpress/block-editor"; import { useMemo, useEffect, useState, createInterpolateElement } from "@wordpress/element"; import { __, sprintf } from "@wordpress/i18n"; import { upload } from "@wordpress/icons"; import { store as noticesStore } from "@wordpress/notices"; import DimensionControls from "./dimension-controls"; import OverlayControls from "./overlay-controls"; import Overlay from "./overlay"; import { useToolsPanelDropdownMenuProps } from "../utils/hooks"; import { unlock } from "../lock-unlock"; const ALLOWED_MEDIA_TYPES = ["image"]; const { ResolutionTool } = unlock(blockEditorPrivateApis); const DEFAULT_MEDIA_SIZE_SLUG = "full"; function FeaturedImageResolutionTool({ image, value, onChange }) { const { imageSizes } = useSelect((select) => { const { getSettings } = select(blockEditorStore); return { imageSizes: getSettings().imageSizes }; }, []); if (!imageSizes?.length) { return null; } const imageSizeOptions = imageSizes.filter( ({ slug }) => image?.media_details?.sizes?.[slug]?.source_url ).map(({ name, slug }) => ({ value: slug, label: name })); return /* @__PURE__ */ jsx( ResolutionTool, { value, defaultValue: DEFAULT_MEDIA_SIZE_SLUG, options: imageSizeOptions, onChange } ); } function PostFeaturedImageEdit({ clientId, attributes, setAttributes, context: { postId, postType: postTypeSlug, queryId } }) { const isDescendentOfQueryLoop = Number.isFinite(queryId); const { isLink, aspectRatio, height, width, scale, sizeSlug, rel, linkTarget, useFirstImageFromPost } = attributes; const [temporaryURL, setTemporaryURL] = useState(); const [storedFeaturedImage, setFeaturedImage] = useEntityProp( "postType", postTypeSlug, "featured_media", postId ); const [postContent] = useEntityProp( "postType", postTypeSlug, "content", postId ); const featuredImage = useMemo(() => { if (storedFeaturedImage) { return storedFeaturedImage; } if (!useFirstImageFromPost) { return; } const imageOpener = /<!--\s+wp:(?:core\/)?image\s+(?<attrs>{(?:(?:[^}]+|}+(?=})|(?!}\s+\/?-->).)*)?}\s+)?-->/.exec( postContent ); const imageId = imageOpener?.groups?.attrs && JSON.parse(imageOpener.groups.attrs)?.id; return imageId; }, [storedFeaturedImage, useFirstImageFromPost, postContent]); const { media, postType, postPermalink } = useSelect( (select) => { const { getEntityRecord, getPostType, getEditedEntityRecord } = select(coreStore); return { media: featuredImage && getEntityRecord("postType", "attachment", featuredImage, { context: "view" }), postType: postTypeSlug && getPostType(postTypeSlug), postPermalink: getEditedEntityRecord( "postType", postTypeSlug, postId )?.link }; }, [featuredImage, postTypeSlug, postId] ); const mediaUrl = media?.media_details?.sizes?.[sizeSlug]?.source_url || media?.source_url; const blockProps = useBlockProps({ style: { width, height, aspectRatio }, className: clsx({ "is-transient": temporaryURL }) }); const borderProps = useBorderProps(attributes); const shadowProps = getShadowClassesAndStyles(attributes); const blockEditingMode = useBlockEditingMode(); const placeholder = (content) => { return /* @__PURE__ */ jsx( Placeholder, { className: clsx( "block-editor-media-placeholder", borderProps.className ), withIllustration: true, style: { height: !!aspectRatio && "100%", width: !!aspectRatio && "100%", ...borderProps.style, ...shadowProps.style }, children: content } ); }; const onSelectImage = (value) => { if (value?.id) { setFeaturedImage(value.id); } if (value?.url && isBlobURL(value.url)) { setTemporaryURL(value.url); } }; const onResetImage = () => { setAttributes({ isLink: false, linkTarget: "_self", rel: "", sizeSlug: void 0 }); setFeaturedImage(0); }; useEffect(() => { if (mediaUrl && temporaryURL) { setTemporaryURL(); } }, [mediaUrl, temporaryURL]); const { createErrorNotice } = useDispatch(noticesStore); const onUploadError = (message) => { createErrorNotice(message, { type: "snackbar" }); setTemporaryURL(); }; const dropdownMenuProps = useToolsPanelDropdownMenuProps(); const controls = blockEditingMode === "default" && /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx(InspectorControls, { group: "color", children: /* @__PURE__ */ jsx( OverlayControls, { attributes, setAttributes, clientId } ) }), /* @__PURE__ */ jsx(InspectorControls, { group: "dimensions", children: /* @__PURE__ */ jsx( DimensionControls, { clientId, attributes, setAttributes, media } ) }), (featuredImage || isDescendentOfQueryLoop || !postId) && /* @__PURE__ */ jsx(InspectorControls, { children: /* @__PURE__ */ jsxs( ToolsPanel, { label: __("Settings"), resetAll: () => { setAttributes({ isLink: false, linkTarget: "_self", rel: "", sizeSlug: DEFAULT_MEDIA_SIZE_SLUG }); }, dropdownMenuProps, children: [ /* @__PURE__ */ jsx( ToolsPanelItem, { label: postType?.labels.singular_name ? sprintf( // translators: %s: Name of the post type e.g: "post". __("Link to %s"), postType.labels.singular_name ) : __("Link to post"), isShownByDefault: true, hasValue: () => !!isLink, onDeselect: () => setAttributes({ isLink: false }), children: /* @__PURE__ */ jsx( ToggleControl, { __nextHasNoMarginBottom: true, label: postType?.labels.singular_name ? sprintf( // translators: %s: Name of the post type e.g: "post". __("Link to %s"), postType.labels.singular_name ) : __("Link to post"), onChange: () => setAttributes({ isLink: !isLink }), checked: isLink } ) } ), isLink && /* @__PURE__ */ jsx( ToolsPanelItem, { label: __("Open in new tab"), isShownByDefault: true, hasValue: () => "_self" !== linkTarget, onDeselect: () => setAttributes({ linkTarget: "_self" }), children: /* @__PURE__ */ jsx( ToggleControl, { __nextHasNoMarginBottom: true, label: __("Open in new tab"), onChange: (value) => setAttributes({ linkTarget: value ? "_blank" : "_self" }), checked: linkTarget === "_blank" } ) } ), isLink && /* @__PURE__ */ jsx( ToolsPanelItem, { label: __("Link relation"), isShownByDefault: true, hasValue: () => !!rel, onDeselect: () => setAttributes({ rel: "" }), children: /* @__PURE__ */ jsx( TextControl, { __next40pxDefaultSize: true, __nextHasNoMarginBottom: true, label: __("Link relation"), help: createInterpolateElement( __( "The <a>Link Relation</a> attribute defines the relationship between a linked resource and the current document." ), { a: /* @__PURE__ */ jsx(ExternalLink, { href: "https://developer.mozilla.org/docs/Web/HTML/Attributes/rel" }) } ), value: rel, onChange: (newRel) => setAttributes({ rel: newRel }) } ) } ), !!media && /* @__PURE__ */ jsx( FeaturedImageResolutionTool, { image: media, value: sizeSlug, onChange: (nextSizeSlug) => setAttributes({ sizeSlug: nextSizeSlug }) } ) ] } ) }) ] }); let image; if (!featuredImage && (isDescendentOfQueryLoop || !postId)) { return /* @__PURE__ */ jsxs(Fragment, { children: [ controls, /* @__PURE__ */ jsxs("div", { ...blockProps, children: [ !!isLink ? /* @__PURE__ */ jsx("a", { href: postPermalink, target: linkTarget, children: placeholder() }) : placeholder(), /* @__PURE__ */ jsx( Overlay, { attributes, setAttributes, clientId } ) ] }) ] }); } const label = __("Add a featured image"); const imageStyles = { ...borderProps.style, ...shadowProps.style, height: aspectRatio ? "100%" : height, width: !!aspectRatio && "100%", objectFit: !!(height || aspectRatio) && scale }; if (!featuredImage && !temporaryURL) { image = /* @__PURE__ */ jsx( MediaPlaceholder, { onSelect: onSelectImage, accept: "image/*", allowedTypes: ALLOWED_MEDIA_TYPES, onError: onUploadError, placeholder, mediaLibraryButton: ({ open }) => { return /* @__PURE__ */ jsx( Button, { __next40pxDefaultSize: true, icon: upload, variant: "primary", label, showTooltip: true, tooltipPosition: "top center", onClick: () => { open(); } } ); } } ); } else { image = !media && !temporaryURL ? placeholder() : /* @__PURE__ */ jsxs(Fragment, { children: [ /* @__PURE__ */ jsx( "img", { className: borderProps.className, src: temporaryURL || mediaUrl, alt: media && media?.alt_text ? sprintf( // translators: %s: The image's alt text. __("Featured image: %s"), media.alt_text ) : __("Featured image"), style: imageStyles } ), temporaryURL && /* @__PURE__ */ jsx(Spinner, {}) ] }); } return /* @__PURE__ */ jsxs(Fragment, { children: [ !temporaryURL && controls, !!media && !isDescendentOfQueryLoop && /* @__PURE__ */ jsx(BlockControls, { group: "other", children: /* @__PURE__ */ jsx( MediaReplaceFlow, { mediaId: featuredImage, mediaURL: mediaUrl, allowedTypes: ALLOWED_MEDIA_TYPES, accept: "image/*", onSelect: onSelectImage, onError: onUploadError, onReset: onResetImage } ) }), /* @__PURE__ */ jsxs("figure", { ...blockProps, children: [ !!isLink ? /* @__PURE__ */ jsx("a", { href: postPermalink, target: linkTarget, children: image }) : image, /* @__PURE__ */ jsx( Overlay, { attributes, setAttributes, clientId } ) ] }) ] }); } export { PostFeaturedImageEdit as default }; //# sourceMappingURL=edit.js.map