@wordpress/block-editor
Version:
270 lines (267 loc) • 10.6 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = exports.BlockSwitcher = void 0;
var _i18n = require("@wordpress/i18n");
var _components = require("@wordpress/components");
var _blocks2 = require("@wordpress/blocks");
var _data = require("@wordpress/data");
var _icons = require("@wordpress/icons");
var _preferences = require("@wordpress/preferences");
var _store = require("../../store");
var _blockIcon = _interopRequireDefault(require("../block-icon"));
var _blockTransformationsMenu = _interopRequireDefault(require("./block-transformations-menu"));
var _blockVariationTransformations = require("./block-variation-transformations");
var _blockStylesMenu = _interopRequireDefault(require("./block-styles-menu"));
var _patternTransformationsMenu = _interopRequireDefault(require("./pattern-transformations-menu"));
var _useBlockDisplayTitle = _interopRequireDefault(require("../block-title/use-block-display-title"));
var _jsxRuntime = require("react/jsx-runtime");
/**
* WordPress dependencies
*/
/**
* Internal dependencies
*/
function BlockSwitcherDropdownMenuContents({
onClose,
clientIds,
hasBlockStyles,
canRemove
}) {
const {
replaceBlocks,
multiSelect,
updateBlockAttributes
} = (0, _data.useDispatch)(_store.store);
const {
possibleBlockTransformations,
patterns,
blocks,
isUsingBindings
} = (0, _data.useSelect)(select => {
const {
getBlockAttributes,
getBlocksByClientId,
getBlockRootClientId,
getBlockTransformItems,
__experimentalGetPatternTransformItems
} = select(_store.store);
const rootClientId = getBlockRootClientId(clientIds[0]);
const _blocks = getBlocksByClientId(clientIds);
return {
blocks: _blocks,
possibleBlockTransformations: getBlockTransformItems(_blocks, rootClientId),
patterns: __experimentalGetPatternTransformItems(_blocks, rootClientId),
isUsingBindings: clientIds.every(clientId => !!getBlockAttributes(clientId)?.metadata?.bindings)
};
}, [clientIds]);
const blockVariationTransformations = (0, _blockVariationTransformations.useBlockVariationTransforms)({
clientIds,
blocks
});
function selectForMultipleBlocks(insertedBlocks) {
if (insertedBlocks.length > 1) {
multiSelect(insertedBlocks[0].clientId, insertedBlocks[insertedBlocks.length - 1].clientId);
}
}
// Simple block transformation based on the `Block Transforms` API.
function onBlockTransform(name) {
const newBlocks = (0, _blocks2.switchToBlockType)(blocks, name);
replaceBlocks(clientIds, newBlocks);
selectForMultipleBlocks(newBlocks);
}
function onBlockVariationTransform(name) {
updateBlockAttributes(blocks[0].clientId, {
...blockVariationTransformations.find(({
name: variationName
}) => variationName === name).attributes
});
}
// Pattern transformation through the `Patterns` API.
function onPatternTransform(transformedBlocks) {
replaceBlocks(clientIds, transformedBlocks);
selectForMultipleBlocks(transformedBlocks);
}
/**
* The `isTemplate` check is a stopgap solution here.
* Ideally, the Transforms API should handle this
* by allowing to exclude blocks from wildcard transformations.
*/
const isSingleBlock = blocks.length === 1;
const isTemplate = isSingleBlock && (0, _blocks2.isTemplatePart)(blocks[0]);
const hasPossibleBlockTransformations = !!possibleBlockTransformations.length && canRemove && !isTemplate;
const hasPossibleBlockVariationTransformations = !!blockVariationTransformations?.length;
const hasPatternTransformation = !!patterns?.length && canRemove;
const hasBlockOrBlockVariationTransforms = hasPossibleBlockTransformations || hasPossibleBlockVariationTransformations;
const hasContents = hasBlockStyles || hasBlockOrBlockVariationTransforms || hasPatternTransformation;
if (!hasContents) {
return /*#__PURE__*/(0, _jsxRuntime.jsx)("p", {
className: "block-editor-block-switcher__no-transforms",
children: (0, _i18n.__)('No transforms.')
});
}
const connectedBlockDescription = isSingleBlock ? (0, _i18n._x)('This block is connected.', 'block toolbar button label and description') : (0, _i18n._x)('These blocks are connected.', 'block toolbar button label and description');
return /*#__PURE__*/(0, _jsxRuntime.jsxs)("div", {
className: "block-editor-block-switcher__container",
children: [hasPatternTransformation && /*#__PURE__*/(0, _jsxRuntime.jsx)(_patternTransformationsMenu.default, {
blocks: blocks,
patterns: patterns,
onSelect: transformedBlocks => {
onPatternTransform(transformedBlocks);
onClose();
}
}), hasBlockOrBlockVariationTransforms && /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockTransformationsMenu.default, {
className: "block-editor-block-switcher__transforms__menugroup",
possibleBlockTransformations: possibleBlockTransformations,
possibleBlockVariationTransformations: blockVariationTransformations,
blocks: blocks,
onSelect: name => {
onBlockTransform(name);
onClose();
},
onSelectVariation: name => {
onBlockVariationTransform(name);
onClose();
}
}), hasBlockStyles && /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockStylesMenu.default, {
hoveredBlock: blocks[0],
onSwitch: onClose
}), isUsingBindings && /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.MenuGroup, {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.__experimentalText, {
className: "block-editor-block-switcher__binding-indicator",
children: connectedBlockDescription
})
})]
});
}
const BlockSwitcher = ({
clientIds
}) => {
const {
hasContentOnlyLocking,
canRemove,
hasBlockStyles,
icon,
invalidBlocks,
isReusable,
isTemplate,
isDisabled
} = (0, _data.useSelect)(select => {
const {
getTemplateLock,
getBlocksByClientId,
getBlockAttributes,
canRemoveBlocks,
getBlockEditingMode
} = select(_store.store);
const {
getBlockStyles,
getBlockType,
getActiveBlockVariation
} = select(_blocks2.store);
const _blocks = getBlocksByClientId(clientIds);
if (!_blocks.length || _blocks.some(block => !block)) {
return {
invalidBlocks: true
};
}
const [{
name: firstBlockName
}] = _blocks;
const _isSingleBlockSelected = _blocks.length === 1;
const blockType = getBlockType(firstBlockName);
const editingMode = getBlockEditingMode(clientIds[0]);
let _icon;
let _hasTemplateLock;
if (_isSingleBlockSelected) {
const match = getActiveBlockVariation(firstBlockName, getBlockAttributes(clientIds[0]));
// Take into account active block variations.
_icon = match?.icon || blockType.icon;
_hasTemplateLock = getTemplateLock(clientIds[0]) === 'contentOnly';
} else {
const isSelectionOfSameType = new Set(_blocks.map(({
name
}) => name)).size === 1;
_hasTemplateLock = clientIds.some(id => getTemplateLock(id) === 'contentOnly');
// When selection consists of blocks of multiple types, display an
// appropriate icon to communicate the non-uniformity.
_icon = isSelectionOfSameType ? blockType.icon : _icons.copy;
}
return {
canRemove: canRemoveBlocks(clientIds),
hasBlockStyles: _isSingleBlockSelected && !!getBlockStyles(firstBlockName)?.length,
icon: _icon,
isReusable: _isSingleBlockSelected && (0, _blocks2.isReusableBlock)(_blocks[0]),
isTemplate: _isSingleBlockSelected && (0, _blocks2.isTemplatePart)(_blocks[0]),
hasContentOnlyLocking: _hasTemplateLock,
isDisabled: editingMode !== 'default'
};
}, [clientIds]);
const blockTitle = (0, _useBlockDisplayTitle.default)({
clientId: clientIds?.[0],
maximumLength: 35
});
const showIconLabels = (0, _data.useSelect)(select => select(_preferences.store).get('core', 'showIconLabels'), []);
if (invalidBlocks) {
return null;
}
const isSingleBlock = clientIds.length === 1;
const blockSwitcherLabel = isSingleBlock ? blockTitle : (0, _i18n.__)('Multiple blocks selected');
const blockIndicatorText = (isReusable || isTemplate) && !showIconLabels && blockTitle ? blockTitle : undefined;
const hideDropdown = isDisabled || !hasBlockStyles && !canRemove || hasContentOnlyLocking;
if (hideDropdown) {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarGroup, {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarButton, {
disabled: true,
className: "block-editor-block-switcher__no-switcher-icon",
title: blockSwitcherLabel,
icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockIcon.default, {
className: "block-editor-block-switcher__toggle",
icon: icon,
showColors: true
}),
text: blockIndicatorText
})
});
}
const blockSwitcherDescription = isSingleBlock ? (0, _i18n.__)('Change block type or style') : (0, _i18n.sprintf)(/* translators: %d: number of blocks. */
(0, _i18n._n)('Change type of %d block', 'Change type of %d blocks', clientIds.length), clientIds.length);
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarGroup, {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarItem, {
children: toggleProps => /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.DropdownMenu, {
className: "block-editor-block-switcher",
label: blockSwitcherLabel,
popoverProps: {
placement: 'bottom-start',
className: 'block-editor-block-switcher__popover'
},
icon: /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockIcon.default, {
className: "block-editor-block-switcher__toggle",
icon: icon,
showColors: true
}),
text: blockIndicatorText,
toggleProps: {
description: blockSwitcherDescription,
...toggleProps
},
menuProps: {
orientation: 'both'
},
children: ({
onClose
}) => /*#__PURE__*/(0, _jsxRuntime.jsx)(BlockSwitcherDropdownMenuContents, {
onClose: onClose,
clientIds: clientIds,
hasBlockStyles: hasBlockStyles,
canRemove: canRemove
})
})
})
});
};
exports.BlockSwitcher = BlockSwitcher;
var _default = exports.default = BlockSwitcher;
//# sourceMappingURL=index.js.map
;