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