@wordpress/block-library
Version:
Block library for the WordPress editor.
710 lines (708 loc) • 28.3 kB
JavaScript
;
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// packages/block-library/src/latest-posts/edit.js
var edit_exports = {};
__export(edit_exports, {
default: () => LatestPostsEdit
});
module.exports = __toCommonJS(edit_exports);
var import_clsx = __toESM(require("clsx"));
var import_components = require("@wordpress/components");
var import_i18n = require("@wordpress/i18n");
var import_date = require("@wordpress/date");
var import_block_editor = require("@wordpress/block-editor");
var import_data = require("@wordpress/data");
var import_icons = require("@wordpress/icons");
var import_core_data = require("@wordpress/core-data");
var import_notices = require("@wordpress/notices");
var import_compose = require("@wordpress/compose");
var import_element = require("@wordpress/element");
var import_constants = require("./constants");
var import_hooks = require("../utils/hooks");
var import_jsx_runtime = require("react/jsx-runtime");
var CATEGORIES_LIST_QUERY = {
per_page: -1,
_fields: "id,name",
context: "view"
};
var USERS_LIST_QUERY = {
per_page: -1,
has_published_posts: ["post"],
context: "view"
};
var imageAlignmentOptions = [
{
value: "none",
icon: import_icons.alignNone,
label: (0, import_i18n.__)("None")
},
{
value: "left",
icon: import_icons.positionLeft,
label: (0, import_i18n.__)("Left")
},
{
value: "center",
icon: import_icons.positionCenter,
label: (0, import_i18n.__)("Center")
},
{
value: "right",
icon: import_icons.positionRight,
label: (0, import_i18n.__)("Right")
}
];
function getFeaturedImageDetails(post, size) {
const image = post._embedded?.["wp:featuredmedia"]?.["0"];
return {
url: image?.media_details?.sizes?.[size]?.source_url ?? image?.source_url,
alt: image?.alt_text
};
}
function getCurrentAuthor(post) {
return post._embedded?.author?.[0];
}
function Controls({ attributes, setAttributes, postCount }) {
const {
postsToShow,
order,
orderBy,
categories,
selectedAuthor,
displayFeaturedImage,
displayPostContentRadio,
displayPostContent,
displayPostDate,
displayAuthor,
postLayout,
columns,
excerptLength,
featuredImageAlign,
featuredImageSizeSlug,
featuredImageSizeWidth,
featuredImageSizeHeight,
addLinkToFeaturedImage
} = attributes;
const {
imageSizes,
defaultImageWidth,
defaultImageHeight,
categoriesList,
authorList
} = (0, import_data.useSelect)(
(select) => {
const { getEntityRecords, getUsers } = select(import_core_data.store);
const settings = select(import_block_editor.store).getSettings();
return {
defaultImageWidth: settings.imageDimensions?.[featuredImageSizeSlug]?.width ?? 0,
defaultImageHeight: settings.imageDimensions?.[featuredImageSizeSlug]?.height ?? 0,
imageSizes: settings.imageSizes,
categoriesList: getEntityRecords(
"taxonomy",
"category",
CATEGORIES_LIST_QUERY
),
authorList: getUsers(USERS_LIST_QUERY)
};
},
[featuredImageSizeSlug]
);
const dropdownMenuProps = (0, import_hooks.useToolsPanelDropdownMenuProps)();
const imageSizeOptions = imageSizes.filter(({ slug }) => slug !== "full").map(({ name, slug }) => ({
value: slug,
label: name
}));
const categorySuggestions = categoriesList?.reduce(
(accumulator, category) => ({
...accumulator,
[category.name]: category
}),
{}
) ?? {};
const selectCategories = (tokens) => {
const hasNoSuggestion = tokens.some(
(token) => typeof token === "string" && !categorySuggestions[token]
);
if (hasNoSuggestion) {
return;
}
const allCategories = tokens.map((token) => {
return typeof token === "string" ? categorySuggestions[token] : token;
});
if (allCategories.includes(null)) {
return false;
}
setAttributes({ categories: allCategories });
};
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
import_components.__experimentalToolsPanel,
{
label: (0, import_i18n.__)("Post content"),
resetAll: () => setAttributes({
displayPostContent: false,
displayPostContentRadio: "excerpt",
excerptLength: import_constants.DEFAULT_EXCERPT_LENGTH
}),
dropdownMenuProps,
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToolsPanelItem,
{
hasValue: () => !!displayPostContent,
label: (0, import_i18n.__)("Display post content"),
onDeselect: () => setAttributes({ displayPostContent: false }),
isShownByDefault: true,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.ToggleControl,
{
__nextHasNoMarginBottom: true,
label: (0, import_i18n.__)("Display post content"),
checked: displayPostContent,
onChange: (value) => setAttributes({ displayPostContent: value })
}
)
}
),
displayPostContent && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToolsPanelItem,
{
hasValue: () => displayPostContentRadio !== "excerpt",
label: (0, import_i18n.__)("Content length"),
onDeselect: () => setAttributes({
displayPostContentRadio: "excerpt"
}),
isShownByDefault: true,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.RadioControl,
{
label: (0, import_i18n.__)("Content length"),
selected: displayPostContentRadio,
options: [
{ label: (0, import_i18n.__)("Excerpt"), value: "excerpt" },
{
label: (0, import_i18n.__)("Full post"),
value: "full_post"
}
],
onChange: (value) => setAttributes({
displayPostContentRadio: value
})
}
)
}
),
displayPostContent && displayPostContentRadio === "excerpt" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToolsPanelItem,
{
hasValue: () => excerptLength !== import_constants.DEFAULT_EXCERPT_LENGTH,
label: (0, import_i18n.__)("Max number of words"),
onDeselect: () => setAttributes({
excerptLength: import_constants.DEFAULT_EXCERPT_LENGTH
}),
isShownByDefault: true,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.RangeControl,
{
__nextHasNoMarginBottom: true,
__next40pxDefaultSize: true,
label: (0, import_i18n.__)("Max number of words"),
value: excerptLength,
onChange: (value) => setAttributes({ excerptLength: value }),
min: import_constants.MIN_EXCERPT_LENGTH,
max: import_constants.MAX_EXCERPT_LENGTH
}
)
}
)
]
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
import_components.__experimentalToolsPanel,
{
label: (0, import_i18n.__)("Post meta"),
resetAll: () => setAttributes({
displayAuthor: false,
displayPostDate: false
}),
dropdownMenuProps,
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToolsPanelItem,
{
hasValue: () => !!displayAuthor,
label: (0, import_i18n.__)("Display author name"),
onDeselect: () => setAttributes({ displayAuthor: false }),
isShownByDefault: true,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.ToggleControl,
{
__nextHasNoMarginBottom: true,
label: (0, import_i18n.__)("Display author name"),
checked: displayAuthor,
onChange: (value) => setAttributes({ displayAuthor: value })
}
)
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToolsPanelItem,
{
hasValue: () => !!displayPostDate,
label: (0, import_i18n.__)("Display post date"),
onDeselect: () => setAttributes({ displayPostDate: false }),
isShownByDefault: true,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.ToggleControl,
{
__nextHasNoMarginBottom: true,
label: (0, import_i18n.__)("Display post date"),
checked: displayPostDate,
onChange: (value) => setAttributes({ displayPostDate: value })
}
)
}
)
]
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
import_components.__experimentalToolsPanel,
{
label: (0, import_i18n.__)("Featured image"),
resetAll: () => setAttributes({
displayFeaturedImage: false,
featuredImageAlign: void 0,
featuredImageSizeSlug: "thumbnail",
featuredImageSizeWidth: null,
featuredImageSizeHeight: null,
addLinkToFeaturedImage: false
}),
dropdownMenuProps,
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToolsPanelItem,
{
hasValue: () => !!displayFeaturedImage,
label: (0, import_i18n.__)("Display featured image"),
onDeselect: () => setAttributes({ displayFeaturedImage: false }),
isShownByDefault: true,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.ToggleControl,
{
__nextHasNoMarginBottom: true,
label: (0, import_i18n.__)("Display featured image"),
checked: displayFeaturedImage,
onChange: (value) => setAttributes({ displayFeaturedImage: value })
}
)
}
),
displayFeaturedImage && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToolsPanelItem,
{
hasValue: () => featuredImageSizeSlug !== "thumbnail" || featuredImageSizeWidth !== null || featuredImageSizeHeight !== null,
label: (0, import_i18n.__)("Image size"),
onDeselect: () => setAttributes({
featuredImageSizeSlug: "thumbnail",
featuredImageSizeWidth: null,
featuredImageSizeHeight: null
}),
isShownByDefault: true,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_block_editor.__experimentalImageSizeControl,
{
onChange: (value) => {
const newAttrs = {};
if (value.hasOwnProperty("width")) {
newAttrs.featuredImageSizeWidth = value.width;
}
if (value.hasOwnProperty("height")) {
newAttrs.featuredImageSizeHeight = value.height;
}
setAttributes(newAttrs);
},
slug: featuredImageSizeSlug,
width: featuredImageSizeWidth,
height: featuredImageSizeHeight,
imageWidth: defaultImageWidth,
imageHeight: defaultImageHeight,
imageSizeOptions,
imageSizeHelp: (0, import_i18n.__)(
"Select the size of the source image."
),
onChangeImage: (value) => setAttributes({
featuredImageSizeSlug: value,
featuredImageSizeWidth: void 0,
featuredImageSizeHeight: void 0
})
}
)
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToolsPanelItem,
{
hasValue: () => !!featuredImageAlign,
label: (0, import_i18n.__)("Image alignment"),
onDeselect: () => setAttributes({
featuredImageAlign: void 0
}),
isShownByDefault: true,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToggleGroupControl,
{
className: "editor-latest-posts-image-alignment-control",
__nextHasNoMarginBottom: true,
__next40pxDefaultSize: true,
label: (0, import_i18n.__)("Image alignment"),
value: featuredImageAlign || "none",
onChange: (value) => setAttributes({
featuredImageAlign: value !== "none" ? value : void 0
}),
children: imageAlignmentOptions.map(
({ value, icon, label }) => {
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToggleGroupControlOptionIcon,
{
value,
icon,
label
},
value
);
}
)
}
)
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToolsPanelItem,
{
hasValue: () => !!addLinkToFeaturedImage,
label: (0, import_i18n.__)("Add link to featured image"),
onDeselect: () => setAttributes({
addLinkToFeaturedImage: false
}),
isShownByDefault: true,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.ToggleControl,
{
__nextHasNoMarginBottom: true,
label: (0, import_i18n.__)("Add link to featured image"),
checked: addLinkToFeaturedImage,
onChange: (value) => setAttributes({
addLinkToFeaturedImage: value
})
}
)
}
)
] })
]
}
),
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
import_components.__experimentalToolsPanel,
{
label: (0, import_i18n.__)("Sorting and filtering"),
resetAll: () => setAttributes({
order: "desc",
orderBy: "date",
postsToShow: 5,
categories: void 0,
selectedAuthor: void 0,
columns: 3
}),
dropdownMenuProps,
children: [
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToolsPanelItem,
{
hasValue: () => order !== "desc" || orderBy !== "date" || postsToShow !== 5 || categories?.length > 0 || !!selectedAuthor,
label: (0, import_i18n.__)("Sort and filter"),
onDeselect: () => setAttributes({
order: "desc",
orderBy: "date",
postsToShow: 5,
categories: void 0,
selectedAuthor: void 0
}),
isShownByDefault: true,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.QueryControls,
{
...{ order, orderBy },
numberOfItems: postsToShow,
onOrderChange: (value) => setAttributes({ order: value }),
onOrderByChange: (value) => setAttributes({ orderBy: value }),
onNumberOfItemsChange: (value) => setAttributes({ postsToShow: value }),
categorySuggestions,
onCategoryChange: selectCategories,
selectedCategories: categories,
onAuthorChange: (value) => setAttributes({
selectedAuthor: "" !== value ? Number(value) : void 0
}),
authorList: authorList ?? [],
selectedAuthorId: selectedAuthor
}
)
}
),
postLayout === "grid" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.__experimentalToolsPanelItem,
{
hasValue: () => columns !== 3,
label: (0, import_i18n.__)("Columns"),
onDeselect: () => setAttributes({
columns: 3
}),
isShownByDefault: true,
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
import_components.RangeControl,
{
__nextHasNoMarginBottom: true,
__next40pxDefaultSize: true,
label: (0, import_i18n.__)("Columns"),
value: columns,
onChange: (value) => setAttributes({ columns: value }),
min: 2,
max: !postCount ? import_constants.MAX_POSTS_COLUMNS : Math.min(import_constants.MAX_POSTS_COLUMNS, postCount),
required: true
}
)
}
)
]
}
)
] });
}
function LatestPostsEdit({ attributes, setAttributes }) {
const instanceId = (0, import_compose.useInstanceId)(LatestPostsEdit);
const {
postsToShow,
order,
orderBy,
categories,
selectedAuthor,
displayFeaturedImage,
displayPostContentRadio,
displayPostContent,
displayPostDate,
displayAuthor,
postLayout,
columns,
excerptLength,
featuredImageAlign,
featuredImageSizeSlug,
featuredImageSizeWidth,
featuredImageSizeHeight,
addLinkToFeaturedImage
} = attributes;
const { latestPosts } = (0, import_data.useSelect)(
(select) => {
const { getEntityRecords } = select(import_core_data.store);
const catIds = categories && categories.length > 0 ? categories.map((cat) => cat.id) : [];
const latestPostsQuery = Object.fromEntries(
Object.entries({
categories: catIds,
author: selectedAuthor,
order,
orderby: orderBy,
per_page: postsToShow,
_embed: "author,wp:featuredmedia",
ignore_sticky: true
}).filter(([, value]) => typeof value !== "undefined")
);
return {
latestPosts: getEntityRecords(
"postType",
"post",
latestPostsQuery
)
};
},
[postsToShow, order, orderBy, categories, selectedAuthor]
);
const { createWarningNotice } = (0, import_data.useDispatch)(import_notices.store);
const showRedirectionPreventedNotice = (event) => {
event.preventDefault();
createWarningNotice((0, import_i18n.__)("Links are disabled in the editor."), {
id: `block-library/core/latest-posts/redirection-prevented/${instanceId}`,
type: "snackbar"
});
};
const hasPosts = !!latestPosts?.length;
const inspectorControls = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_block_editor.InspectorControls, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
Controls,
{
attributes,
setAttributes,
postCount: latestPosts?.length ?? 0
}
) });
const blockProps = (0, import_block_editor.useBlockProps)({
className: (0, import_clsx.default)({
"wp-block-latest-posts__list": true,
"is-grid": postLayout === "grid",
"has-dates": displayPostDate,
"has-author": displayAuthor,
[`columns-${columns}`]: postLayout === "grid"
})
});
if (!hasPosts) {
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ...blockProps, children: [
inspectorControls,
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Placeholder, { icon: import_icons.pin, label: (0, import_i18n.__)("Latest Posts"), children: !Array.isArray(latestPosts) ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.Spinner, {}) : (0, import_i18n.__)("No posts found.") })
] });
}
const displayPosts = latestPosts.length > postsToShow ? latestPosts.slice(0, postsToShow) : latestPosts;
const layoutControls = [
{
icon: import_icons.list,
title: (0, import_i18n._x)("List view", "Latest posts block display setting"),
onClick: () => setAttributes({ postLayout: "list" }),
isActive: postLayout === "list"
},
{
icon: import_icons.grid,
title: (0, import_i18n._x)("Grid view", "Latest posts block display setting"),
onClick: () => setAttributes({ postLayout: "grid" }),
isActive: postLayout === "grid"
}
];
const dateFormat = (0, import_date.getSettings)().formats.date;
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
inspectorControls,
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_block_editor.BlockControls, { children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_components.ToolbarGroup, { controls: layoutControls }) }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("ul", { ...blockProps, children: displayPosts.map((post) => {
const titleTrimmed = post.title.rendered.trim();
let excerpt = post.excerpt.rendered;
const currentAuthor = getCurrentAuthor(post);
const excerptElement = document.createElement("div");
excerptElement.innerHTML = excerpt;
excerpt = excerptElement.textContent || excerptElement.innerText || "";
const { url: imageSourceUrl, alt: featuredImageAlt } = getFeaturedImageDetails(post, featuredImageSizeSlug);
const imageClasses = (0, import_clsx.default)({
"wp-block-latest-posts__featured-image": true,
[`align${featuredImageAlign}`]: !!featuredImageAlign
});
const renderFeaturedImage = displayFeaturedImage && imageSourceUrl;
const featuredImage = renderFeaturedImage && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"img",
{
src: imageSourceUrl,
alt: featuredImageAlt,
style: {
maxWidth: featuredImageSizeWidth,
maxHeight: featuredImageSizeHeight
}
}
);
const needsReadMore = excerptLength < excerpt.trim().split(" ").length && post.excerpt.raw === "";
const postExcerpt = needsReadMore ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
excerpt.trim().split(" ", excerptLength).join(" "),
(0, import_element.createInterpolateElement)(
(0, import_i18n.sprintf)(
/* translators: 1: Hidden accessibility text: Post title */
(0, import_i18n.__)(
"\u2026 <a>Read more<span>: %1$s</span></a>"
),
titleTrimmed || (0, import_i18n.__)("(no title)")
),
{
a: (
// eslint-disable-next-line jsx-a11y/anchor-has-content
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"a",
{
className: "wp-block-latest-posts__read-more",
href: post.link,
rel: "noopener noreferrer",
onClick: showRedirectionPreventedNotice
}
)
),
span: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "screen-reader-text" })
}
)
] }) : excerpt;
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("li", { children: [
renderFeaturedImage && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: imageClasses, children: addLinkToFeaturedImage ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"a",
{
href: post.link,
onClick: showRedirectionPreventedNotice,
children: featuredImage
}
) : featuredImage }),
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"a",
{
className: "wp-block-latest-posts__post-title",
href: post.link,
dangerouslySetInnerHTML: !!titleTrimmed ? {
__html: titleTrimmed
} : void 0,
onClick: showRedirectionPreventedNotice,
children: !titleTrimmed ? (0, import_i18n.__)("(no title)") : null
}
),
displayAuthor && currentAuthor && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "wp-block-latest-posts__post-author", children: (0, import_i18n.sprintf)(
/* translators: byline. %s: author. */
(0, import_i18n.__)("by %s"),
currentAuthor.name
) }),
displayPostDate && post.date_gmt && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"time",
{
dateTime: (0, import_date.format)("c", post.date_gmt),
className: "wp-block-latest-posts__post-date",
children: (0, import_date.dateI18n)(dateFormat, post.date_gmt)
}
),
displayPostContent && displayPostContentRadio === "excerpt" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "wp-block-latest-posts__post-excerpt", children: postExcerpt }),
displayPostContent && displayPostContentRadio === "full_post" && /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
"div",
{
className: "wp-block-latest-posts__post-full-content",
dangerouslySetInnerHTML: {
__html: post.content.raw.trim()
}
}
)
] }, post.id);
}) })
] });
}
//# sourceMappingURL=edit.js.map