UNPKG

@wordpress/block-library

Version:
216 lines (215 loc) 7.66 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"; 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; } var { openMediaEditorModalKey } = unlock(blockEditorPrivateApis); var ATTACHMENT_EDIT_QUERY = { context: "edit" }; 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 }) { const { id, url, alt, caption } = attributes; const registry = useRegistry(); const openMediaEditorModal = useSelect( (select) => select(blockEditorStore).getSettings()[openMediaEditorModalKey], [] ); const blockMetadataRef = useRef({ alt, caption: caption?.toString() }); const mediaEditorMetadataBaselineRef = useRef(); const mediaEditorMetadataSyncRequestRef = useRef(0); useEffect(() => { blockMetadataRef.current = { alt, caption: caption?.toString() }; }, [alt, caption]); const getCachedAttachmentRecord = useCallback( (attachmentId) => { const { getEditedEntityRecord, getEntityRecord } = registry.select(coreStore); return getEditedEntityRecord( "postType", "attachment", attachmentId ) || getEntityRecord( "postType", "attachment", attachmentId, ATTACHMENT_EDIT_QUERY ) || getEntityRecord("postType", "attachment", attachmentId); }, [registry] ); const resolveAttachmentRecord = useCallback( async (attachmentId) => { const resolveSelect = registry.resolveSelect(coreStore); try { return await resolveSelect.getEntityRecord( "postType", "attachment", attachmentId, ATTACHMENT_EDIT_QUERY ) || 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 ]); invalidateResolution("getEntityRecord", [ "postType", "attachment", attachmentId, ATTACHMENT_EDIT_QUERY ]); 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 = {}; if (newId !== id) { nextAttributes.id = newId; nextAttributes.url = newUrl ?? url; } if (originalAttachment) { const resolvedAttachment = await resolveFreshAttachmentRecord(newId); if (syncRequest !== mediaEditorMetadataSyncRequestRef.current) { return; } const resolvedMetadataAttributes = getSyncedImageBlockAttributes( blockMetadataRef.current, originalAttachment, resolvedAttachment ); if (Object.keys(resolvedMetadataAttributes).length) { Object.assign(nextAttributes, resolvedMetadataAttributes); blockMetadataRef.current = { ...blockMetadataRef.current, ...resolvedMetadataAttributes }; } } if (Object.keys(nextAttributes).length) { setAttributes(nextAttributes); } }, [id, resolveFreshAttachmentRecord, setAttributes, url] ); const openImageMediaEditorModal = useCallback(async () => { if (!id || !openMediaEditorModal) { return; } const cachedAttachmentRecord = getCachedAttachmentRecord(id); const fallbackAttachmentRecord = getAttachmentFallbackForEmptyBlockMetadata( blockMetadataRef.current ); const resolvedAttachmentRecord = hasKnownAttachmentMetadata( cachedAttachmentRecord ) ? void 0 : await resolveAttachmentRecord(id); mediaEditorMetadataBaselineRef.current = resolvedAttachmentRecord || (hasKnownAttachmentMetadata(cachedAttachmentRecord) ? cachedAttachmentRecord : fallbackAttachmentRecord) || cachedAttachmentRecord; openMediaEditorModal({ id, onUpdate: handleMediaUpdate }); }, [ getCachedAttachmentRecord, handleMediaUpdate, id, openMediaEditorModal, resolveAttachmentRecord ]); return id && openMediaEditorModal ? openImageMediaEditorModal : void 0; } export { getImageBlockMetadataFromAttachment, getSyncedImageBlockAttributes, useOpenImageMediaEditorModal }; //# sourceMappingURL=use-open-image-media-editor-modal.mjs.map