UNPKG

@wordpress/block-library

Version:
293 lines (292 loc) 9.81 kB
// packages/block-library/src/image/use-open-image-media-editor-modal.js import { store as coreStore } from "@wordpress/core-data"; import { privateApis as blockEditorPrivateApis, store as blockEditorStore } from "@wordpress/block-editor"; import { __unstableStripHTML as stripHTML } from "@wordpress/dom"; import { useRegistry, useSelect } from "@wordpress/data"; import { useCallback, useEffect, useRef } from "@wordpress/element"; import { unlock } from "../lock-unlock.mjs"; import { DEFAULT_MEDIA_SIZE_SLUG, LINK_DESTINATION_ATTACHMENT, LINK_DESTINATION_MEDIA } from "./constants.mjs"; function normalizeImageBlockCaption(caption) { if (typeof caption !== "string") { return ""; } const textContent = stripHTML(caption).trim(); if (!textContent) { return ""; } return caption.replace(/\n/g, "<br>"); } function getAttachmentCaption(attachment) { const caption = attachment?.caption; if (typeof caption === "string") { return normalizeImageBlockCaption(caption); } if (caption && typeof caption === "object" && Object.hasOwn(caption, "raw")) { return normalizeImageBlockCaption(caption.raw); } return void 0; } function getImageBlockMetadataFromAttachment(attachment) { return { alt: typeof attachment?.alt_text === "string" ? attachment.alt_text : attachment?.alt || "", caption: getAttachmentCaption(attachment) }; } function normalizeMetadataAttribute(value) { return value || ""; } function getSyncedImageBlockAttributes(currentAttributes, originalAttachment, updatedAttachment) { if (!originalAttachment || !updatedAttachment) { return {}; } const originalMetadata = getImageBlockMetadataFromAttachment(originalAttachment); const updatedMetadata = getImageBlockMetadataFromAttachment(updatedAttachment); const syncedAttributes = {}; const normalizedCurrentAlt = normalizeMetadataAttribute( currentAttributes.alt ); if (originalMetadata.alt !== updatedMetadata.alt && (normalizedCurrentAlt === originalMetadata.alt || !normalizedCurrentAlt)) { syncedAttributes.alt = updatedMetadata.alt; } const normalizedCurrentCaption = normalizeMetadataAttribute( currentAttributes.caption ); if (originalMetadata.caption !== void 0 && updatedMetadata.caption !== void 0 && originalMetadata.caption !== updatedMetadata.caption && (normalizedCurrentCaption === originalMetadata.caption || !normalizedCurrentCaption)) { syncedAttributes.caption = updatedMetadata.caption || void 0; } return syncedAttributes; } function getNewAttachmentSizeAttributes(sizeSlug, attachment) { const sizes = attachment.media_details?.sizes; if (!sizeSlug || sizeSlug === DEFAULT_MEDIA_SIZE_SLUG || !sizes) { return void 0; } const sizeUrl = sizes[sizeSlug]?.source_url; if (sizeUrl) { return { url: sizeUrl }; } const fullUrl = attachment.source_url ?? sizes.full?.source_url; return fullUrl ? { url: fullUrl, sizeSlug: DEFAULT_MEDIA_SIZE_SLUG } : void 0; } function getNewAttachmentLinkAttributes(linkDestination, attachment) { if (linkDestination === LINK_DESTINATION_MEDIA) { return attachment.source_url ? { href: attachment.source_url } : void 0; } if (linkDestination === LINK_DESTINATION_ATTACHMENT) { return attachment.link ? { href: attachment.link } : void 0; } return void 0; } function getNewAttachmentImageBlockAttributes(blockAttributes, attachment) { if (!attachment) { return void 0; } return { ...getNewAttachmentSizeAttributes( blockAttributes.sizeSlug, attachment ), ...getNewAttachmentLinkAttributes( blockAttributes.linkDestination, attachment ) }; } var { openMediaEditorModalKey } = unlock(blockEditorPrivateApis); function getAttachmentFallbackForEmptyBlockMetadata({ alt, caption }) { const attachment = {}; if (!alt) { attachment.alt_text = ""; } if (!caption?.toString()) { attachment.caption = ""; } return Object.keys(attachment).length ? attachment : void 0; } function hasKnownAttachmentMetadata(attachment) { if (!attachment) { return false; } const hasKnownAlt = typeof attachment.alt_text === "string" || typeof attachment.alt === "string"; const hasKnownCaption = getImageBlockMetadataFromAttachment(attachment).caption !== void 0; return hasKnownAlt && hasKnownCaption; } function useOpenImageMediaEditorModal({ attributes, setAttributes, onClose, onUrlChange }) { const { id, url, alt, caption, sizeSlug, linkDestination } = attributes; const registry = useRegistry(); const openMediaEditorModal = useSelect( (select) => select(blockEditorStore).getSettings()[openMediaEditorModalKey], [] ); const blockAttributesRef = useRef({ id, url, alt, caption: caption?.toString(), sizeSlug, linkDestination }); const mediaEditorMetadataBaselineRef = useRef(); const mediaEditorMetadataSyncRequestRef = useRef(0); useEffect(() => { blockAttributesRef.current = { id, url, alt, caption: caption?.toString(), sizeSlug, linkDestination }; }, [alt, caption, id, linkDestination, sizeSlug, url]); const getCachedAttachmentRecord = useCallback( (attachmentId) => registry.select(coreStore).getEditedEntityRecord( "postType", "attachment", attachmentId ), [registry] ); const resolveAttachmentRecord = useCallback( async (attachmentId) => { const resolveSelect = registry.resolveSelect(coreStore); try { return await resolveSelect.getEntityRecord( "postType", "attachment", attachmentId ); } catch { return void 0; } }, [registry] ); const resolveFreshAttachmentRecord = useCallback( async (attachmentId) => { const { invalidateResolution } = registry.dispatch(coreStore); invalidateResolution("getEntityRecord", [ "postType", "attachment", attachmentId ]); return resolveAttachmentRecord(attachmentId); }, [registry, resolveAttachmentRecord] ); const handleMediaUpdate = useCallback( async ({ id: newId, url: newUrl }) => { if (typeof newId !== "number") { return; } const originalAttachment = mediaEditorMetadataBaselineRef.current; mediaEditorMetadataBaselineRef.current = void 0; const syncRequest = ++mediaEditorMetadataSyncRequestRef.current; const nextAttributes = {}; const currentBlockAttributes = blockAttributesRef.current; const isNewAttachment = newId !== currentBlockAttributes.id; if (isNewAttachment) { nextAttributes.id = newId; nextAttributes.url = newUrl ?? currentBlockAttributes.url; if (nextAttributes.url !== currentBlockAttributes.url) { onUrlChange?.(nextAttributes.url); } blockAttributesRef.current = { ...blockAttributesRef.current, id: nextAttributes.id, url: nextAttributes.url }; } if (originalAttachment || isNewAttachment) { const resolvedAttachment = await resolveFreshAttachmentRecord(newId); if (syncRequest !== mediaEditorMetadataSyncRequestRef.current) { return; } const attachmentRecord = resolvedAttachment ?? getCachedAttachmentRecord(newId); const latestBlockAttributes = blockAttributesRef.current; if (originalAttachment) { const resolvedMetadataAttributes = getSyncedImageBlockAttributes( latestBlockAttributes, originalAttachment, attachmentRecord ); if (Object.keys(resolvedMetadataAttributes).length) { Object.assign( nextAttributes, resolvedMetadataAttributes ); } } if (isNewAttachment) { const derivedAttributes = getNewAttachmentImageBlockAttributes( latestBlockAttributes, attachmentRecord ); if (derivedAttributes) { Object.assign(nextAttributes, derivedAttributes); if (derivedAttributes.url && derivedAttributes.url !== latestBlockAttributes.url) { onUrlChange?.(derivedAttributes.url); } } } } if (Object.keys(nextAttributes).length) { blockAttributesRef.current = { ...blockAttributesRef.current, ...nextAttributes }; setAttributes(nextAttributes); } }, [ getCachedAttachmentRecord, onUrlChange, resolveFreshAttachmentRecord, setAttributes ] ); const openImageMediaEditorModal = useCallback(async () => { if (!id || !openMediaEditorModal) { return; } const cachedAttachmentRecord = getCachedAttachmentRecord(id); const fallbackAttachmentRecord = getAttachmentFallbackForEmptyBlockMetadata( blockAttributesRef.current ); const resolvedAttachmentRecord = hasKnownAttachmentMetadata( cachedAttachmentRecord ) ? void 0 : await resolveAttachmentRecord(id); mediaEditorMetadataBaselineRef.current = resolvedAttachmentRecord || (hasKnownAttachmentMetadata(cachedAttachmentRecord) ? cachedAttachmentRecord : fallbackAttachmentRecord) || cachedAttachmentRecord; openMediaEditorModal({ id, onUpdate: handleMediaUpdate, onClose }); }, [ getCachedAttachmentRecord, handleMediaUpdate, id, onClose, openMediaEditorModal, resolveAttachmentRecord ]); return id && openMediaEditorModal ? openImageMediaEditorModal : void 0; } export { getImageBlockMetadataFromAttachment, getNewAttachmentImageBlockAttributes, getSyncedImageBlockAttributes, useOpenImageMediaEditorModal }; //# sourceMappingURL=use-open-image-media-editor-modal.mjs.map