@wordpress/block-library
Version:
Block library for the WordPress editor.
224 lines (223 loc) • 7.43 kB
JavaScript
// packages/block-library/src/table-of-contents/edit.js
import {
BlockControls,
BlockIcon,
InspectorControls,
store as blockEditorStore,
useBlockProps
} from "@wordpress/block-editor";
import { createBlock } from "@wordpress/blocks";
import {
Placeholder,
ToggleControl,
SelectControl,
ToolbarButton,
ToolbarGroup,
__experimentalToolsPanel as ToolsPanel,
__experimentalToolsPanelItem as ToolsPanelItem
} from "@wordpress/components";
import { useDispatch, useSelect } from "@wordpress/data";
import { renderToString } from "@wordpress/element";
import { __, isRTL } from "@wordpress/i18n";
import { useInstanceId } from "@wordpress/compose";
import { store as noticeStore } from "@wordpress/notices";
import {
tableOfContents as icon,
formatListBullets,
formatListBulletsRTL,
formatListNumbered,
formatListNumberedRTL
} from "@wordpress/icons";
import TableOfContentsList from "./list";
import { linearToNestedHeadingList } from "./utils";
import { useObserveHeadings } from "./hooks";
import { useToolsPanelDropdownMenuProps } from "../utils/hooks";
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
function TableOfContentsEdit({
attributes: {
headings = [],
onlyIncludeCurrentPage,
maxLevel,
ordered = true
},
clientId,
setAttributes
}) {
useObserveHeadings(clientId);
const blockProps = useBlockProps();
const instanceId = useInstanceId(
TableOfContentsEdit,
"table-of-contents"
);
const { createWarningNotice } = useDispatch(noticeStore);
const showRedirectionPreventedNotice = (event) => {
event.preventDefault();
createWarningNotice(__("Links are disabled in the editor."), {
id: `block-library/core/table-of-contents/redirection-prevented/${instanceId}`,
type: "snackbar"
});
};
const canInsertList = useSelect(
(select) => {
const { getBlockRootClientId, canInsertBlockType } = select(blockEditorStore);
const rootClientId = getBlockRootClientId(clientId);
return canInsertBlockType("core/list", rootClientId);
},
[clientId]
);
const { replaceBlocks } = useDispatch(blockEditorStore);
const dropdownMenuProps = useToolsPanelDropdownMenuProps();
const headingTree = linearToNestedHeadingList(headings);
const toolbarControls = /* @__PURE__ */ jsxs(BlockControls, { children: [
/* @__PURE__ */ jsxs(ToolbarGroup, { children: [
/* @__PURE__ */ jsx(
ToolbarButton,
{
icon: isRTL() ? formatListBulletsRTL : formatListBullets,
title: __("Unordered"),
description: __("Convert to unordered list"),
onClick: () => setAttributes({ ordered: false }),
isActive: ordered === false
}
),
/* @__PURE__ */ jsx(
ToolbarButton,
{
icon: isRTL() ? formatListNumberedRTL : formatListNumbered,
title: __("Ordered"),
description: __("Convert to ordered list"),
onClick: () => setAttributes({ ordered: true }),
isActive: ordered === true
}
)
] }),
canInsertList && /* @__PURE__ */ jsx(ToolbarGroup, { children: /* @__PURE__ */ jsx(
ToolbarButton,
{
onClick: () => replaceBlocks(
clientId,
createBlock("core/list", {
ordered,
values: renderToString(
/* @__PURE__ */ jsx(
TableOfContentsList,
{
nestedHeadingList: headingTree,
ordered
}
)
)
})
),
children: __("Convert to static list")
}
) })
] });
const inspectorControls = /* @__PURE__ */ jsx(InspectorControls, { children: /* @__PURE__ */ jsxs(
ToolsPanel,
{
label: __("Settings"),
resetAll: () => {
setAttributes({
onlyIncludeCurrentPage: false,
maxLevel: void 0,
ordered: true
});
},
dropdownMenuProps,
children: [
/* @__PURE__ */ jsx(
ToolsPanelItem,
{
hasValue: () => !!onlyIncludeCurrentPage,
label: __("Only include current page"),
onDeselect: () => setAttributes({ onlyIncludeCurrentPage: false }),
isShownByDefault: true,
children: /* @__PURE__ */ jsx(
ToggleControl,
{
__nextHasNoMarginBottom: true,
label: __("Only include current page"),
checked: onlyIncludeCurrentPage,
onChange: (value) => setAttributes({ onlyIncludeCurrentPage: value }),
help: onlyIncludeCurrentPage ? __(
"Only including headings from the current page (if the post is paginated)."
) : __(
"Include headings from all pages (if the post is paginated)."
)
}
)
}
),
/* @__PURE__ */ jsx(
ToolsPanelItem,
{
hasValue: () => !!maxLevel,
label: __("Limit heading levels"),
onDeselect: () => setAttributes({ maxLevel: void 0 }),
isShownByDefault: true,
children: /* @__PURE__ */ jsx(
SelectControl,
{
__nextHasNoMarginBottom: true,
__next40pxDefaultSize: true,
label: __("Include headings down to level"),
value: maxLevel || "",
options: [
{ value: "", label: __("All levels") },
{ value: "1", label: __("Heading 1") },
{ value: "2", label: __("Heading 2") },
{ value: "3", label: __("Heading 3") },
{ value: "4", label: __("Heading 4") },
{ value: "5", label: __("Heading 5") },
{ value: "6", label: __("Heading 6") }
],
onChange: (value) => setAttributes({
maxLevel: value ? parseInt(value) : void 0
}),
help: !maxLevel ? __(
"Including all heading levels in the table of contents."
) : __(
"Only include headings up to and including this level."
)
}
)
}
)
]
}
) });
if (headings.length === 0) {
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx("div", { ...blockProps, children: /* @__PURE__ */ jsx(
Placeholder,
{
icon: /* @__PURE__ */ jsx(BlockIcon, { icon }),
label: __("Table of Contents"),
instructions: __(
"Start adding Heading blocks to create a table of contents. Headings with HTML anchors will be linked here."
)
}
) }),
inspectorControls
] });
}
const ListTag = ordered ? "ol" : "ul";
return /* @__PURE__ */ jsxs(Fragment, { children: [
/* @__PURE__ */ jsx("nav", { ...blockProps, children: /* @__PURE__ */ jsx(ListTag, { children: /* @__PURE__ */ jsx(
TableOfContentsList,
{
nestedHeadingList: headingTree,
disableLinkActivation: true,
onClick: showRedirectionPreventedNotice,
ordered
}
) }) }),
toolbarControls,
inspectorControls
] });
}
export {
TableOfContentsEdit as default
};
//# sourceMappingURL=edit.js.map