@wordpress/block-editor
Version:
145 lines (134 loc) • 4.8 kB
JavaScript
import { createElement, Fragment } from "@wordpress/element";
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { MenuGroup, MenuItem } from '@wordpress/components';
import { getBlockMenuDefaultClassName, switchToBlockType } from '@wordpress/blocks';
import { useState, useMemo } from '@wordpress/element';
/**
* Internal dependencies
*/
import BlockIcon from '../block-icon';
import PreviewBlockPopover from './preview-block-popover';
import BlockVariationTransformations from './block-variation-transformations';
/**
* Helper hook to group transformations to display them in a specific order in the UI.
* For now we group only priority content driven transformations(ex. paragraph -> heading).
*
* Later on we could also group 'layout' transformations(ex. paragraph -> group) and
* display them in different sections.
*
* @param {Object[]} possibleBlockTransformations The available block transformations.
* @return {Record<string, Object[]>} The grouped block transformations.
*/
function useGroupedTransforms(possibleBlockTransformations) {
const priorityContentTranformationBlocks = {
'core/paragraph': 1,
'core/heading': 2,
'core/list': 3,
'core/quote': 4
};
const transformations = useMemo(() => {
const priorityTextTranformsNames = Object.keys(priorityContentTranformationBlocks);
return possibleBlockTransformations.reduce((accumulator, item) => {
const {
name
} = item;
if (priorityTextTranformsNames.includes(name)) {
accumulator.priorityTextTransformations.push(item);
} else {
accumulator.restTransformations.push(item);
}
return accumulator;
}, {
priorityTextTransformations: [],
restTransformations: []
});
}, [possibleBlockTransformations]); // Order the priority text transformations.
transformations.priorityTextTransformations.sort(({
name: currentName
}, {
name: nextName
}) => {
return priorityContentTranformationBlocks[currentName] < priorityContentTranformationBlocks[nextName] ? -1 : 1;
});
return transformations;
}
const BlockTransformationsMenu = ({
className,
possibleBlockTransformations,
possibleBlockVariationTransformations,
onSelect,
onSelectVariation,
blocks
}) => {
const [hoveredTransformItemName, setHoveredTransformItemName] = useState();
const {
priorityTextTransformations,
restTransformations
} = useGroupedTransforms(possibleBlockTransformations); // We have to check if both content transformations(priority and rest) are set
// in order to create a separate MenuGroup for them.
const hasBothContentTransformations = priorityTextTransformations.length && restTransformations.length;
const restTransformItems = !!restTransformations.length && createElement(RestTransformationItems, {
restTransformations: restTransformations,
onSelect: onSelect,
setHoveredTransformItemName: setHoveredTransformItemName
});
return createElement(Fragment, null, createElement(MenuGroup, {
label: __('Transform to'),
className: className
}, hoveredTransformItemName && createElement(PreviewBlockPopover, {
blocks: switchToBlockType(blocks, hoveredTransformItemName)
}), !!possibleBlockVariationTransformations?.length && createElement(BlockVariationTransformations, {
transformations: possibleBlockVariationTransformations,
blocks: blocks,
onSelect: onSelectVariation
}), priorityTextTransformations.map(item => createElement(BlockTranformationItem, {
key: item.name,
item: item,
onSelect: onSelect,
setHoveredTransformItemName: setHoveredTransformItemName
})), !hasBothContentTransformations && restTransformItems), !!hasBothContentTransformations && createElement(MenuGroup, {
className: className
}, restTransformItems));
};
function RestTransformationItems({
restTransformations,
onSelect,
setHoveredTransformItemName
}) {
return restTransformations.map(item => createElement(BlockTranformationItem, {
key: item.name,
item: item,
onSelect: onSelect,
setHoveredTransformItemName: setHoveredTransformItemName
}));
}
function BlockTranformationItem({
item,
onSelect,
setHoveredTransformItemName
}) {
const {
name,
icon,
title,
isDisabled
} = item;
return createElement(MenuItem, {
className: getBlockMenuDefaultClassName(name),
onClick: event => {
event.preventDefault();
onSelect(name);
},
disabled: isDisabled,
onMouseLeave: () => setHoveredTransformItemName(null),
onMouseEnter: () => setHoveredTransformItemName(name)
}, createElement(BlockIcon, {
icon: icon,
showColors: true
}), title);
}
export default BlockTransformationsMenu;
//# sourceMappingURL=block-transformations-menu.js.map