@wordpress/block-library
Version:
Block library for the WordPress editor.
333 lines (332 loc) • 10.3 kB
JavaScript
// packages/block-library/src/post-author/edit.js
import clsx from "clsx";
import {
AlignmentControl,
BlockControls,
InspectorControls,
RichText,
useBlockProps
} from "@wordpress/block-editor";
import {
ComboboxControl,
SelectControl,
ToggleControl,
__experimentalToolsPanel as ToolsPanel,
__experimentalToolsPanelItem as ToolsPanelItem
} from "@wordpress/components";
import { debounce } from "@wordpress/compose";
import { store as coreStore } from "@wordpress/core-data";
import { useDispatch, useSelect } from "@wordpress/data";
import { useMemo, useState } from "@wordpress/element";
import { decodeEntities } from "@wordpress/html-entities";
import { __, sprintf } from "@wordpress/i18n";
import {
useDefaultAvatar,
useToolsPanelDropdownMenuProps
} from "../utils/hooks.mjs";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
var AUTHORS_QUERY = {
who: "authors",
per_page: 100,
_fields: "id,name",
context: "view"
};
function AuthorCombobox({ value, onChange }) {
const [filterValue, setFilterValue] = useState("");
const { authors, isLoading } = useSelect(
(select) => {
const { getUsers, isResolving } = select(coreStore);
const query = { ...AUTHORS_QUERY };
if (filterValue) {
query.search = filterValue;
query.search_columns = ["name"];
}
return {
authors: getUsers(query),
isLoading: isResolving("getUsers", [query])
};
},
[filterValue]
);
const authorOptions = useMemo(() => {
const fetchedAuthors = (authors ?? []).map((author) => {
return {
value: author.id,
label: decodeEntities(author.name)
};
});
const foundAuthor = fetchedAuthors.findIndex(
(fetchedAuthor) => value?.id === fetchedAuthor.value
);
let currentAuthor = [];
if (foundAuthor < 0 && value) {
currentAuthor = [
{
value: value.id,
label: decodeEntities(value.name)
}
];
} else if (foundAuthor < 0 && !value) {
currentAuthor = [
{
value: 0,
label: __("(No author)")
}
];
}
return [...currentAuthor, ...fetchedAuthors];
}, [authors, value]);
return /* @__PURE__ */ jsx(
ComboboxControl,
{
__next40pxDefaultSize: true,
label: __("Author"),
options: authorOptions,
value: value?.id,
onFilterValueChange: debounce(setFilterValue, 300),
onChange,
allowReset: false,
isLoading
}
);
}
function PostAuthorEdit({
isSelected,
context: { postType, postId, queryId },
attributes,
setAttributes
}) {
const isDescendentOfQueryLoop = Number.isFinite(queryId);
const dropdownMenuProps = useToolsPanelDropdownMenuProps();
const defaultAvatar = useDefaultAvatar();
const { authorDetails, canAssignAuthor, supportsAuthor } = useSelect(
(select) => {
const { getEditedEntityRecord, getUser, getPostType } = select(coreStore);
const currentPost = getEditedEntityRecord(
"postType",
postType,
postId
);
const authorId = currentPost?.author;
return {
authorDetails: authorId ? getUser(authorId, { context: "view" }) : null,
supportsAuthor: getPostType(postType)?.supports?.author ?? false,
canAssignAuthor: currentPost?._links?.["wp:action-assign-author"] ? true : false
};
},
[postType, postId]
);
const { editEntityRecord } = useDispatch(coreStore);
const {
textAlign,
showAvatar,
showBio,
byline,
isLink,
linkTarget,
avatarSize
} = attributes;
const avatarSizes = [];
const authorName = authorDetails?.name || __("Post Author");
if (authorDetails?.avatar_urls) {
Object.keys(authorDetails.avatar_urls).forEach((size) => {
avatarSizes.push({
value: size,
label: `${size} x ${size}`
});
});
}
const blockProps = useBlockProps({
className: clsx({
[`has-text-align-${textAlign}`]: textAlign
})
});
const handleSelect = (nextAuthorId) => {
editEntityRecord("postType", postType, postId, {
author: nextAuthorId
});
};
const showAuthorControl = !!postId && !isDescendentOfQueryLoop && canAssignAuthor;
if (!supportsAuthor && postType !== void 0) {
return /* @__PURE__ */ jsx("div", { ...blockProps, children: sprintf(
// translators: %s: Name of the post type e.g: "post".
__("This post type (%s) does not support the author."),
postType
) });
}
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx(InspectorControls, { children: /* @__PURE__ */ jsxs(
ToolsPanel,
{
label: __("Settings"),
resetAll: () => {
setAttributes({
avatarSize: 48,
showAvatar: true,
isLink: false,
linkTarget: "_self"
});
},
dropdownMenuProps,
children: [
showAuthorControl && /* @__PURE__ */ jsx("div", { style: { gridColumn: "1 / -1" }, children: /* @__PURE__ */ jsx(
AuthorCombobox,
{
value: authorDetails,
onChange: handleSelect
}
) }),
/* @__PURE__ */ jsx(
ToolsPanelItem,
{
label: __("Show avatar"),
isShownByDefault: true,
hasValue: () => !showAvatar,
onDeselect: () => setAttributes({ showAvatar: true }),
children: /* @__PURE__ */ jsx(
ToggleControl,
{
label: __("Show avatar"),
checked: showAvatar,
onChange: () => setAttributes({
showAvatar: !showAvatar
})
}
)
}
),
showAvatar && /* @__PURE__ */ jsx(
ToolsPanelItem,
{
label: __("Avatar size"),
isShownByDefault: true,
hasValue: () => avatarSize !== 48,
onDeselect: () => setAttributes({ avatarSize: 48 }),
children: /* @__PURE__ */ jsx(
SelectControl,
{
__next40pxDefaultSize: true,
label: __("Avatar size"),
value: avatarSize,
options: avatarSizes,
onChange: (size) => {
setAttributes({
avatarSize: Number(size)
});
}
}
)
}
),
/* @__PURE__ */ jsx(
ToolsPanelItem,
{
label: __("Show bio"),
isShownByDefault: true,
hasValue: () => !!showBio,
onDeselect: () => setAttributes({ showBio: void 0 }),
children: /* @__PURE__ */ jsx(
ToggleControl,
{
label: __("Show bio"),
checked: !!showBio,
onChange: () => setAttributes({ showBio: !showBio })
}
)
}
),
/* @__PURE__ */ jsx(
ToolsPanelItem,
{
label: __("Link author name to author page"),
isShownByDefault: true,
hasValue: () => !!isLink,
onDeselect: () => setAttributes({ isLink: false }),
children: /* @__PURE__ */ jsx(
ToggleControl,
{
label: __("Link author name to author page"),
checked: isLink,
onChange: () => setAttributes({ isLink: !isLink })
}
)
}
),
isLink && /* @__PURE__ */ jsx(
ToolsPanelItem,
{
label: __("Link target"),
isShownByDefault: true,
hasValue: () => linkTarget !== "_self",
onDeselect: () => setAttributes({ linkTarget: "_self" }),
children: /* @__PURE__ */ jsx(
ToggleControl,
{
label: __("Open in new tab"),
onChange: (value) => setAttributes({
linkTarget: value ? "_blank" : "_self"
}),
checked: linkTarget === "_blank"
}
)
}
)
]
}
) }),
/* @__PURE__ */ jsx(BlockControls, { group: "block", children: /* @__PURE__ */ jsx(
AlignmentControl,
{
value: textAlign,
onChange: (nextAlign) => {
setAttributes({ textAlign: nextAlign });
}
}
) }),
/* @__PURE__ */ jsxs("div", { ...blockProps, children: [
showAvatar && /* @__PURE__ */ jsx("div", { className: "wp-block-post-author__avatar", children: /* @__PURE__ */ jsx(
"img",
{
width: avatarSize,
src: authorDetails?.avatar_urls?.[avatarSize] || defaultAvatar,
alt: authorDetails?.name || __("Default Avatar")
}
) }),
/* @__PURE__ */ jsxs("div", { className: "wp-block-post-author__content", children: [
(!RichText.isEmpty(byline) || isSelected) && /* @__PURE__ */ jsx(
RichText,
{
identifier: "byline",
className: "wp-block-post-author__byline",
"aria-label": __("Post author byline text"),
placeholder: __("Write byline\u2026"),
value: byline,
onChange: (value) => setAttributes({ byline: value })
}
),
/* @__PURE__ */ jsx("p", { className: "wp-block-post-author__name", children: isLink ? /* @__PURE__ */ jsx(
"a",
{
href: "#post-author-pseudo-link",
onClick: (event) => event.preventDefault(),
children: authorName
}
) : authorName }),
showBio && /* @__PURE__ */ jsx(
"p",
{
className: "wp-block-post-author__bio",
dangerouslySetInnerHTML: {
__html: authorDetails?.description
}
}
)
] })
] })
] });
}
var edit_default = PostAuthorEdit;
export {
edit_default as default
};
//# sourceMappingURL=edit.mjs.map