@gechiui/block-editor
Version:
191 lines (172 loc) • 6.82 kB
JavaScript
import { createElement, Fragment } from "@gechiui/element";
/**
* External dependencies
*/
import { castArray, uniq } from 'lodash';
/**
* GeChiUI dependencies
*/
import { __, _n, sprintf } from '@gechiui/i18n';
import { DropdownMenu, ToolbarButton, ToolbarGroup, ToolbarItem } from '@gechiui/components';
import { switchToBlockType, store as blocksStore, isReusableBlock, isTemplatePart } from '@gechiui/blocks';
import { useSelect, useDispatch } from '@gechiui/data';
import { stack } from '@gechiui/icons';
/**
* Internal dependencies
*/
import { store as blockEditorStore } from '../../store';
import useBlockDisplayInformation from '../use-block-display-information';
import BlockIcon from '../block-icon';
import BlockTitle from '../block-title';
import BlockTransformationsMenu from './block-transformations-menu';
import BlockStylesMenu from './block-styles-menu';
import PatternTransformationsMenu from './pattern-transformations-menu';
export const BlockSwitcherDropdownMenu = _ref => {
let {
clientIds,
blocks
} = _ref;
const {
replaceBlocks
} = useDispatch(blockEditorStore);
const blockInformation = useBlockDisplayInformation(blocks[0].clientId);
const {
possibleBlockTransformations,
canRemove,
hasBlockStyles,
icon,
blockTitle,
patterns
} = useSelect(select => {
var _getBlockType2;
const {
getBlockRootClientId,
getBlockTransformItems,
__experimentalGetPatternTransformItems
} = select(blockEditorStore);
const {
getBlockStyles,
getBlockType
} = select(blocksStore);
const {
canRemoveBlocks
} = select(blockEditorStore);
const rootClientId = getBlockRootClientId(castArray(clientIds)[0]);
const [{
name: firstBlockName
}] = blocks;
const _isSingleBlockSelected = blocks.length === 1;
const styles = _isSingleBlockSelected && getBlockStyles(firstBlockName);
let _icon;
if (_isSingleBlockSelected) {
_icon = blockInformation === null || blockInformation === void 0 ? void 0 : blockInformation.icon; // Take into account active block variations.
} else {
var _getBlockType;
const isSelectionOfSameType = uniq(blocks.map(_ref2 => {
let {
name
} = _ref2;
return name;
})).length === 1; // When selection consists of blocks of multiple types, display an
// appropriate icon to communicate the non-uniformity.
_icon = isSelectionOfSameType ? (_getBlockType = getBlockType(firstBlockName)) === null || _getBlockType === void 0 ? void 0 : _getBlockType.icon : stack;
}
return {
possibleBlockTransformations: getBlockTransformItems(blocks, rootClientId),
canRemove: canRemoveBlocks(clientIds, rootClientId),
hasBlockStyles: !!(styles !== null && styles !== void 0 && styles.length),
icon: _icon,
blockTitle: (_getBlockType2 = getBlockType(firstBlockName)) === null || _getBlockType2 === void 0 ? void 0 : _getBlockType2.title,
patterns: __experimentalGetPatternTransformItems(blocks, rootClientId)
};
}, [clientIds, blocks, blockInformation === null || blockInformation === void 0 ? void 0 : blockInformation.icon]);
const isReusable = blocks.length === 1 && isReusableBlock(blocks[0]);
const isTemplate = blocks.length === 1 && isTemplatePart(blocks[0]); // Simple block tranformation based on the `Block Transforms` API.
const onBlockTransform = name => replaceBlocks(clientIds, switchToBlockType(blocks, name)); // Pattern transformation through the `Patterns` API.
const onPatternTransform = transformedBlocks => replaceBlocks(clientIds, transformedBlocks);
const hasPossibleBlockTransformations = !!possibleBlockTransformations.length && canRemove;
const hasPatternTransformation = !!(patterns !== null && patterns !== void 0 && patterns.length) && canRemove;
if (!hasBlockStyles && !hasPossibleBlockTransformations) {
return createElement(ToolbarGroup, null, createElement(ToolbarButton, {
disabled: true,
className: "block-editor-block-switcher__no-switcher-icon",
title: blockTitle,
icon: createElement(BlockIcon, {
icon: icon,
showColors: true
})
}));
}
const blockSwitcherLabel = blockTitle;
const blockSwitcherDescription = 1 === blocks.length ? sprintf(
/* translators: %s: block title. */
__('%s:更改区块类型或样式'), blockTitle) : sprintf(
/* translators: %d: number of blocks. */
_n('修改%d个区块的类型', 'Change type of %d blocks', blocks.length), blocks.length);
const showDropDown = hasBlockStyles || hasPossibleBlockTransformations || hasPatternTransformation;
return createElement(ToolbarGroup, null, createElement(ToolbarItem, null, toggleProps => createElement(DropdownMenu, {
className: "block-editor-block-switcher",
label: blockSwitcherLabel,
popoverProps: {
position: 'bottom right',
isAlternate: true,
className: 'block-editor-block-switcher__popover'
},
icon: createElement(Fragment, null, createElement(BlockIcon, {
icon: icon,
className: "block-editor-block-switcher__toggle",
showColors: true
}), (isReusable || isTemplate) && createElement("span", {
className: "block-editor-block-switcher__toggle-text"
}, createElement(BlockTitle, {
clientId: clientIds
}))),
toggleProps: {
describedBy: blockSwitcherDescription,
...toggleProps
},
menuProps: {
orientation: 'both'
}
}, _ref3 => {
let {
onClose
} = _ref3;
return showDropDown && createElement("div", {
className: "block-editor-block-switcher__container"
}, hasPatternTransformation && createElement(PatternTransformationsMenu, {
blocks: blocks,
patterns: patterns,
onSelect: transformedBlocks => {
onPatternTransform(transformedBlocks);
onClose();
}
}), hasPossibleBlockTransformations && createElement(BlockTransformationsMenu, {
className: "block-editor-block-switcher__transforms__menugroup",
possibleBlockTransformations: possibleBlockTransformations,
blocks: blocks,
onSelect: name => {
onBlockTransform(name);
onClose();
}
}), hasBlockStyles && createElement(BlockStylesMenu, {
hoveredBlock: blocks[0],
onSwitch: onClose
}));
})));
};
export const BlockSwitcher = _ref4 => {
let {
clientIds
} = _ref4;
const blocks = useSelect(select => select(blockEditorStore).getBlocksByClientId(clientIds), [clientIds]);
if (!blocks.length || blocks.some(block => !block)) {
return null;
}
return createElement(BlockSwitcherDropdownMenu, {
clientIds: clientIds,
blocks: blocks
});
};
export default BlockSwitcher;
//# sourceMappingURL=index.js.map