@wordpress/block-library
Version:
Block library for the WordPress editor.
250 lines (249 loc) • 7.5 kB
JavaScript
// packages/block-library/src/navigation-link/link-ui/index.js
import { __unstableStripHTML as stripHTML } from "@wordpress/dom";
import {
Popover,
Button,
VisuallyHidden,
__experimentalVStack as VStack
} from "@wordpress/components";
import { __ } from "@wordpress/i18n";
import { LinkControl, useBlockEditingMode } from "@wordpress/block-editor";
import {
useMemo,
useState,
useRef,
useEffect,
forwardRef
} from "@wordpress/element";
import { useResourcePermissions } from "@wordpress/core-data";
import { plus } from "@wordpress/icons";
import { useInstanceId } from "@wordpress/compose";
import { LinkUIPageCreator } from "./page-creator";
import LinkUIBlockInserter from "./block-inserter";
import { useEntityBinding } from "../shared/use-entity-binding";
import { jsx, jsxs } from "react/jsx-runtime";
function getSuggestionsQuery(type, kind) {
switch (type) {
case "post":
case "page":
return { type: "post", subtype: type };
case "category":
return { type: "term", subtype: "category" };
case "tag":
return { type: "term", subtype: "post_tag" };
case "post_format":
return { type: "post-format" };
default:
if (kind === "taxonomy") {
return { type: "term", subtype: type };
}
if (kind === "post-type") {
return { type: "post", subtype: type };
}
return {
// for custom link which has no type
// always show pages as initial suggestions
initialSuggestionsSearchOptions: {
type: "post",
subtype: "page",
perPage: 20
}
};
}
}
function UnforwardedLinkUI(props, ref) {
const { label, url, opensInNewTab, type, kind, id } = props.link;
const { clientId } = props;
const postType = type || "page";
const [addingBlock, setAddingBlock] = useState(false);
const [addingPage, setAddingPage] = useState(false);
const [focusAddBlockButton, setFocusAddBlockButton] = useState(false);
const [focusAddPageButton, setFocusAddPageButton] = useState(false);
const permissions = useResourcePermissions({
kind: "postType",
name: postType
});
const { isBoundEntityAvailable } = useEntityBinding({
clientId,
attributes: props.link
});
const link = useMemo(
() => ({
url,
opensInNewTab,
title: label && stripHTML(label),
kind,
type,
id
}),
[label, opensInNewTab, url, kind, type, id]
);
const handlePageCreated = (pageLink) => {
props.onChange(pageLink);
setAddingPage(false);
};
const dialogTitleId = useInstanceId(
LinkUI,
"link-ui-link-control__title"
);
const dialogDescriptionId = useInstanceId(
LinkUI,
"link-ui-link-control__description"
);
const blockEditingMode = useBlockEditingMode();
return /* @__PURE__ */ jsxs(
Popover,
{
ref,
placement: "bottom",
onClose: props.onClose,
anchor: props.anchor,
shift: true,
children: [
!addingBlock && !addingPage && /* @__PURE__ */ jsxs(
"div",
{
role: "dialog",
"aria-labelledby": dialogTitleId,
"aria-describedby": dialogDescriptionId,
children: [
/* @__PURE__ */ jsxs(VisuallyHidden, { children: [
/* @__PURE__ */ jsx("h2", { id: dialogTitleId, children: __("Add link") }),
/* @__PURE__ */ jsx("p", { id: dialogDescriptionId, children: __(
"Search for and add a link to your Navigation."
) })
] }),
/* @__PURE__ */ jsx(
LinkControl,
{
hasTextControl: true,
hasRichPreviews: true,
value: link,
showInitialSuggestions: true,
withCreateSuggestion: false,
noDirectEntry: !!type,
noURLSuggestion: !!type,
suggestionsQuery: getSuggestionsQuery(type, kind),
onChange: props.onChange,
onRemove: props.onRemove,
onCancel: props.onCancel,
handleEntities: isBoundEntityAvailable,
renderControlBottom: () => {
if (link?.url?.length) {
return null;
}
return /* @__PURE__ */ jsx(
LinkUITools,
{
focusAddBlockButton,
focusAddPageButton,
setAddingBlock: () => {
setAddingBlock(true);
setFocusAddBlockButton(false);
},
setAddingPage: () => {
setAddingPage(true);
setFocusAddPageButton(false);
},
canAddPage: permissions?.canCreate && type === "page",
canAddBlock: blockEditingMode === "default"
}
);
}
}
)
]
}
),
addingBlock && /* @__PURE__ */ jsx(
LinkUIBlockInserter,
{
clientId: props.clientId,
onBack: () => {
setAddingBlock(false);
setFocusAddBlockButton(true);
setFocusAddPageButton(false);
},
onBlockInsert: props?.onBlockInsert
}
),
addingPage && /* @__PURE__ */ jsx(
LinkUIPageCreator,
{
postType,
onBack: () => {
setAddingPage(false);
setFocusAddPageButton(true);
setFocusAddBlockButton(false);
},
onPageCreated: handlePageCreated,
initialTitle: link?.url || ""
}
)
]
}
);
}
var LinkUI = forwardRef(UnforwardedLinkUI);
var LinkUITools = ({
setAddingBlock,
setAddingPage,
focusAddBlockButton,
focusAddPageButton,
canAddPage,
canAddBlock
}) => {
const blockInserterAriaRole = "listbox";
const addBlockButtonRef = useRef();
const addPageButtonRef = useRef();
useEffect(() => {
if (focusAddBlockButton) {
addBlockButtonRef.current?.focus();
}
}, [focusAddBlockButton]);
useEffect(() => {
if (focusAddPageButton) {
addPageButtonRef.current?.focus();
}
}, [focusAddPageButton]);
if (!canAddPage && !canAddBlock) {
return null;
}
return /* @__PURE__ */ jsxs(VStack, { spacing: 0, className: "link-ui-tools", children: [
canAddPage && /* @__PURE__ */ jsx(
Button,
{
__next40pxDefaultSize: true,
ref: addPageButtonRef,
icon: plus,
onClick: (e) => {
e.preventDefault();
setAddingPage(true);
},
"aria-haspopup": blockInserterAriaRole,
children: __("Create page")
}
),
canAddBlock && /* @__PURE__ */ jsx(
Button,
{
__next40pxDefaultSize: true,
ref: addBlockButtonRef,
icon: plus,
onClick: (e) => {
e.preventDefault();
setAddingBlock(true);
},
"aria-haspopup": blockInserterAriaRole,
children: __("Add block")
}
)
] });
};
var link_ui_default = LinkUITools;
export {
LinkUI,
link_ui_default as default,
getSuggestionsQuery
};
//# sourceMappingURL=index.js.map