UNPKG

@wordpress/block-library

Version:
175 lines (174 loc) 5.82 kB
// packages/block-library/src/gallery/use-dynamic-gallery.js import { useMemo } from "@wordpress/element"; import { useDispatch, useSelect, useRegistry } from "@wordpress/data"; import { store as blockEditorStore } from "@wordpress/block-editor"; import { store as coreStore } from "@wordpress/core-data"; import { createBlock } from "@wordpress/blocks"; import { pickRelevantMediaFiles } from "./shared.mjs"; import { getHrefAndDestination } from "./utils.mjs"; import { getUpdatedLinkTargetSettings } from "../image/utils.mjs"; import { getSourceQuery, getDynamicSource, ATTACHED_MEDIA, DEFAULT_ORDERBY, DEFAULT_ORDER, MAX_IMAGES } from "./dynamic-source.mjs"; var EMPTY_ARRAY = []; function buildImageBlockAttributes(media, galleryAttributes) { const { sizeSlug, linkTo, linkTarget, aspectRatio } = galleryAttributes; const hasAspectRatio = !!aspectRatio && aspectRatio !== "auto"; return { id: media.id, ...pickRelevantMediaFiles(media, sizeSlug), ...getHrefAndDestination(media, linkTo), ...getUpdatedLinkTargetSettings(linkTarget, galleryAttributes), sizeSlug, // Raw caption, mirroring the frontend (`index.php`). Gap: the REST API // exposes no caption run through `wp_get_attachment_caption`, so neither // side applies that filter. caption: media.caption?.raw || "", alt: media.alt_text || "", aspectRatio: hasAspectRatio ? aspectRatio : void 0, // Pair `scale` with `aspectRatio` so the image crops rather than stretches, // matching the image block's UI and the frontend (`index.php`). scale: hasAspectRatio ? "cover" : void 0 }; } function buildImageBlocks(media, galleryAttributes) { return media.map( (mediaItem) => createBlock( "core/image", buildImageBlockAttributes(mediaItem, galleryAttributes) ) ); } function useDynamicGallery({ attributes, setAttributes, clientId, postId, postType }) { const { dynamicContent } = attributes; const canUseDynamicSource = !!postType; const sourceDescriptor = getDynamicSource(dynamicContent?.source); const sourceOrderby = dynamicContent?.args?.orderBy ?? DEFAULT_ORDERBY; const sourceOrder = dynamicContent?.args?.order ?? DEFAULT_ORDER; const registry = useRegistry(); const { replaceInnerBlocks, __unstableMarkNextChangeAsNotPersistent } = useDispatch(blockEditorStore); const query = useMemo( () => dynamicContent ? getSourceQuery(dynamicContent, { postId }) : null, [dynamicContent, postId] ); const { dynamicMedia, dynamicMediaTotal, isResolvingDynamic } = useSelect( (select) => { if (!query) { return { dynamicMedia: EMPTY_ARRAY, dynamicMediaTotal: 0, isResolvingDynamic: false }; } const selectorArgs = ["postType", "attachment", query]; return { dynamicMedia: select(coreStore).getEntityRecords(...selectorArgs) ?? EMPTY_ARRAY, // Total matching attachments (the `X-WP-Total` header), which the // query's `per_page` cap doesn't bound — so it reveals when the // post has more attached images than are shown. dynamicMediaTotal: select(coreStore).getEntityRecordsTotalItems( ...selectorArgs ) ?? 0, isResolvingDynamic: !select(coreStore).hasFinishedResolution( "getEntityRecords", selectorArgs ) }; }, [query] ); const hasMoreImagesThanCap = dynamicMediaTotal > MAX_IMAGES; const { sizeSlug, linkTo, linkTarget, aspectRatio } = attributes; const imageAttributes = useMemo( () => ({ sizeSlug, linkTo, linkTarget, aspectRatio }), [sizeSlug, linkTo, linkTarget, aspectRatio] ); const dynamicImageBlocks = useMemo( () => buildImageBlocks(dynamicMedia, imageAttributes), [dynamicMedia, imageAttributes] ); const galleryContext = useMemo( () => ({ allowResize: attributes.allowResize ?? false, imageCrop: attributes.imageCrop, fixedHeight: attributes.fixedHeight, navigationButtonType: attributes.navigationButtonType }), [ attributes.allowResize, attributes.imageCrop, attributes.fixedHeight, attributes.navigationButtonType ] ); function enableDynamicMode() { registry.batch(() => { setAttributes({ dynamicContent: { source: ATTACHED_MEDIA } }); __unstableMarkNextChangeAsNotPersistent(); replaceInnerBlocks(clientId, []); }); } function convertToStatic() { registry.batch(() => { replaceInnerBlocks( clientId, buildImageBlocks(dynamicMedia, imageAttributes) ); __unstableMarkNextChangeAsNotPersistent(); setAttributes({ dynamicContent: void 0 }); }); } function setSourceOrder(nextOrderby, nextOrder) { const nextArgs = { ...dynamicContent?.args }; delete nextArgs.orderBy; delete nextArgs.order; if (nextOrderby !== void 0 && (nextOrderby !== DEFAULT_ORDERBY || nextOrder !== DEFAULT_ORDER)) { nextArgs.orderBy = nextOrderby; nextArgs.order = nextOrder; } const nextSource = { ...dynamicContent }; if (Object.keys(nextArgs).length) { nextSource.args = nextArgs; } else { delete nextSource.args; } setAttributes({ dynamicContent: nextSource }); } function resetSource() { setAttributes({ dynamicContent: { source: dynamicContent.source } }); } return { dynamicContent, canUseDynamicSource, sourceDescriptor, hasMoreImagesThanCap, dynamicMediaTotal, sourceOrderby, sourceOrder, dynamicMedia, dynamicImageBlocks, isResolvingDynamic, galleryContext, enableDynamicMode, convertToStatic, setSourceOrder, resetSource }; } export { useDynamicGallery as default }; //# sourceMappingURL=use-dynamic-gallery.mjs.map