@wordpress/block-library
Version:
Block library for the WordPress editor.
216 lines (215 loc) • 7.66 kB
JavaScript
// 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