@wordpress/block-library
Version:
Block library for the WordPress editor.
127 lines (120 loc) • 4.01 kB
JavaScript
/**
* WordPress dependencies
*/
import { createBlock } from '@wordpress/blocks';
import { useDispatch } from '@wordpress/data';
import { store as blockEditorStore } from '@wordpress/block-editor';
/**
* Converts an array of pages into a nested array of navigation link blocks.
*
* @param {Array} pages An array of pages.
*
* @return {Array} A nested array of navigation link blocks.
*/
function createNavigationLinks(pages = []) {
const linkMap = {};
const navigationLinks = [];
pages.forEach(({
id,
title,
link: url,
type,
parent
}) => {
var _linkMap$id$innerBloc;
// See if a placeholder exists. This is created if children appear before parents in list.
const innerBlocks = (_linkMap$id$innerBloc = linkMap[id]?.innerBlocks) !== null && _linkMap$id$innerBloc !== void 0 ? _linkMap$id$innerBloc : [];
linkMap[id] = createBlock('core/navigation-link', {
id,
label: title.rendered,
url,
type,
kind: 'post-type'
}, innerBlocks);
if (!parent) {
navigationLinks.push(linkMap[id]);
} else {
if (!linkMap[parent]) {
// Use a placeholder if the child appears before parent in list.
linkMap[parent] = {
innerBlocks: []
};
}
// Although these variables are not referenced, they are needed to store the innerBlocks in memory.
const parentLinkInnerBlocks = linkMap[parent].innerBlocks;
parentLinkInnerBlocks.push(linkMap[id]);
}
});
return navigationLinks;
}
/**
* Finds a navigation link block by id, recursively.
* It might be possible to make this a more generic helper function.
*
* @param {Array} navigationLinks An array of navigation link blocks.
* @param {number} id The id of the navigation link to find.
*
* @return {Object|null} The navigation link block with the given id.
*/
function findNavigationLinkById(navigationLinks, id) {
for (const navigationLink of navigationLinks) {
// Is this the link we're looking for?
if (navigationLink.attributes.id === id) {
return navigationLink;
}
// If not does it have innerBlocks?
if (navigationLink.innerBlocks && navigationLink.innerBlocks.length) {
const foundNavigationLink = findNavigationLinkById(navigationLink.innerBlocks, id);
if (foundNavigationLink) {
return foundNavigationLink;
}
}
}
return null;
}
export function convertToNavigationLinks(pages = [], parentPageID = null) {
let navigationLinks = createNavigationLinks(pages);
// If a parent page ID is provided, only return the children of that page.
if (parentPageID) {
const parentPage = findNavigationLinkById(navigationLinks, parentPageID);
if (parentPage && parentPage.innerBlocks) {
navigationLinks = parentPage.innerBlocks;
}
}
// Transform all links with innerBlocks into Submenus. This can't be done
// sooner because page objects have no information on their children.
const transformSubmenus = listOfLinks => {
listOfLinks.forEach((block, index, listOfLinksArray) => {
const {
attributes,
innerBlocks
} = block;
if (innerBlocks.length !== 0) {
transformSubmenus(innerBlocks);
const transformedBlock = createBlock('core/navigation-submenu', attributes, innerBlocks);
listOfLinksArray[index] = transformedBlock;
}
});
};
transformSubmenus(navigationLinks);
return navigationLinks;
}
export function useConvertToNavigationLinks({
clientId,
pages,
parentClientId,
parentPageID
}) {
const {
replaceBlock,
selectBlock
} = useDispatch(blockEditorStore);
return () => {
const navigationLinks = convertToNavigationLinks(pages, parentPageID);
// Replace the Page List block with the Navigation Links.
replaceBlock(clientId, navigationLinks);
// Select the Navigation block to reveal the changes.
selectBlock(parentClientId);
};
}
//# sourceMappingURL=use-convert-to-navigation-links.js.map