@wordpress/block-editor
Version:
378 lines (371 loc) • 13.8 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _reactNative = require("react-native");
var _components = require("@wordpress/components");
var _blocks = require("@wordpress/blocks");
var _i18n = require("@wordpress/i18n");
var _data = require("@wordpress/data");
var _compose = require("@wordpress/compose");
var _icons = require("@wordpress/icons");
var _element = require("@wordpress/element");
var _notices = require("@wordpress/notices");
var _reusableBlocks = require("@wordpress/reusable-blocks");
var _coreData = require("@wordpress/core-data");
var _moverDescription = require("../block-mover/mover-description");
var _store = require("../../store");
var _blockTransformationsMenu = _interopRequireDefault(require("../block-switcher/block-transformations-menu"));
var _convertToGroupButtons = require("../convert-to-group-buttons");
var _jsxRuntime = require("react/jsx-runtime");
/**
* External dependencies
*/
/**
* WordPress dependencies
*/
// Disable Reason: Needs to be refactored.
// eslint-disable-next-line no-restricted-imports
/**
* Internal dependencies
*/
const BlockActionsMenu = ({
// Select.
blockTitle,
canInsertBlockType,
getBlocksByClientId,
isEmptyDefaultBlock,
isLocked,
canDuplicate,
isFirst,
isLast,
isReusableBlockType,
reusableBlock,
rootClientId,
selectedBlockClientId,
selectedBlockPossibleTransformations,
// Dispatch.
createSuccessNotice,
convertToRegularBlocks,
duplicateBlock,
onMoveDown,
onMoveUp,
openGeneralSidebar,
pasteBlock,
removeBlocks,
// Passed in.
anchorNodeRef,
isStackedHorizontally,
onDelete,
wrapBlockMover,
wrapBlockSettings
}) => {
const [clipboard, setCurrentClipboard] = (0, _element.useState)((0, _components.getClipboard)());
const blockActionsMenuPickerRef = (0, _element.useRef)();
const blockTransformationMenuPickerRef = (0, _element.useRef)();
const moversOptions = {
keys: ['icon', 'actionTitle']
};
const clipboardBlock = clipboard && (0, _blocks.rawHandler)({
HTML: clipboard
})[0];
const isPasteEnabled = clipboardBlock && canInsertBlockType(clipboardBlock.name, rootClientId);
const innerBlockCount = (0, _data.useSelect)(select => select(_store.store).getBlockCount(selectedBlockClientId), [selectedBlockClientId]);
const {
actionTitle: {
backward: backwardButtonTitle,
forward: forwardButtonTitle
}
} = (0, _moverDescription.getMoversSetup)(isStackedHorizontally, moversOptions);
// Check if selected block is Groupable and/or Ungroupable.
const convertToGroupButtonProps = (0, _convertToGroupButtons.useConvertToGroupButtonProps)(
// `selectedBlockClientId` can be undefined in some cases where this
// component gets re-rendered right after the block is removed.
selectedBlockClientId ? [selectedBlockClientId] : []);
const {
isGroupable,
isUngroupable
} = convertToGroupButtonProps;
const showConvertToGroupButton = isGroupable || isUngroupable;
const convertToGroupButtons = (0, _convertToGroupButtons.useConvertToGroupButtons)({
...convertToGroupButtonProps
});
const allOptions = {
settings: {
id: 'settingsOption',
label: (0, _i18n.__)('Block settings'),
value: 'settingsOption',
onSelect: openGeneralSidebar
},
backwardButton: {
id: 'backwardButtonOption',
label: backwardButtonTitle,
value: 'backwardButtonOption',
disabled: isFirst,
onSelect: onMoveUp
},
forwardButton: {
id: 'forwardButtonOption',
label: forwardButtonTitle,
value: 'forwardButtonOption',
disabled: isLast,
onSelect: onMoveDown
},
delete: {
id: 'deleteOption',
label: (0, _i18n.__)('Remove block'),
value: 'deleteOption',
separated: true,
disabled: isEmptyDefaultBlock,
onSelect: () => {
onDelete();
createSuccessNotice(
// translators: displayed right after the block is removed.
(0, _i18n.__)('Block removed'));
}
},
transformButton: {
id: 'transformButtonOption',
label: (0, _i18n.__)('Transform block…'),
value: 'transformButtonOption',
onSelect: () => {
if (blockTransformationMenuPickerRef.current) {
blockTransformationMenuPickerRef.current.presentPicker();
}
}
},
copyButton: {
id: 'copyButtonOption',
label: (0, _i18n.__)('Copy'),
value: 'copyButtonOption',
onSelect: () => {
const serializedBlock = (0, _blocks.serialize)(getBlocksByClientId(selectedBlockClientId));
setCurrentClipboard(serializedBlock);
(0, _components.setClipboard)(serializedBlock);
createSuccessNotice(
// translators: displayed right after the block is copied.
(0, _i18n.__)('Block copied'));
}
},
cutButton: {
id: 'cutButtonOption',
label: (0, _i18n.__)('Cut block'),
value: 'cutButtonOption',
onSelect: () => {
(0, _components.setClipboard)((0, _blocks.serialize)(getBlocksByClientId(selectedBlockClientId)));
removeBlocks(selectedBlockClientId);
createSuccessNotice(
// translators: displayed right after the block is cut.
(0, _i18n.__)('Block cut'));
}
},
pasteButton: {
id: 'pasteButtonOption',
label: (0, _i18n.__)('Paste block after'),
value: 'pasteButtonOption',
onSelect: () => {
onPasteBlock();
createSuccessNotice(
// translators: displayed right after the block is pasted.
(0, _i18n.__)('Block pasted'));
}
},
duplicateButton: {
id: 'duplicateButtonOption',
label: (0, _i18n.__)('Duplicate block'),
value: 'duplicateButtonOption',
onSelect: () => {
duplicateBlock();
createSuccessNotice(
// translators: displayed right after the block is duplicated.
(0, _i18n.__)('Block duplicated'));
}
},
convertToRegularBlocks: {
id: 'convertToRegularBlocksOption',
label: (0, _i18n.__)('Detach'),
value: 'convertToRegularBlocksOption',
onSelect: () => {
/* translators: %s: name of the synced block */
const successNotice = (0, _i18n.__)('%s detached');
createSuccessNotice((0, _i18n.sprintf)(successNotice, reusableBlock?.title?.raw || blockTitle));
convertToRegularBlocks();
}
}
};
const options = [wrapBlockMover && allOptions.backwardButton, wrapBlockMover && allOptions.forwardButton, wrapBlockSettings && allOptions.settings, !isLocked && selectedBlockPossibleTransformations.length && allOptions.transformButton, canDuplicate && allOptions.copyButton, canDuplicate && allOptions.cutButton, canDuplicate && isPasteEnabled && allOptions.pasteButton, canDuplicate && allOptions.duplicateButton, showConvertToGroupButton && isGroupable && convertToGroupButtons.group, showConvertToGroupButton && isUngroupable && convertToGroupButtons.ungroup, isReusableBlockType && innerBlockCount > 0 && allOptions.convertToRegularBlocks, !isLocked && allOptions.delete].filter(Boolean);
// End early if there are no options to show.
if (!options.length) {
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarGroup, {
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarButton, {
title: (0, _i18n.__)('Open Block Actions Menu'),
icon: _icons.moreHorizontalMobile,
disabled: true
})
});
}
function onPasteBlock() {
if (!clipboard) {
return;
}
pasteBlock((0, _blocks.rawHandler)({
HTML: clipboard
})[0]);
}
function onPickerSelect(value) {
const selectedItem = options.find(item => item.value === value);
selectedItem.onSelect();
}
function onPickerPresent() {
if (blockActionsMenuPickerRef.current) {
blockActionsMenuPickerRef.current.presentPicker();
}
}
const disabledButtonIndices = options.map((option, index) => option.disabled && index + 1).filter(Boolean);
const accessibilityHint = _reactNative.Platform.OS === 'ios' ? (0, _i18n.__)('Double tap to open Action Sheet with available options') : (0, _i18n.__)('Double tap to open Bottom Sheet with available options');
const getAnchor = () => anchorNodeRef ? (0, _reactNative.findNodeHandle)(anchorNodeRef) : undefined;
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_components.ToolbarGroup, {
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_components.ToolbarButton, {
title: (0, _i18n.__)('Open Block Actions Menu'),
onClick: onPickerPresent,
icon: _icons.moreHorizontalMobile,
extraProps: {
hint: accessibilityHint
}
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_components.Picker, {
testID: "block-actions-menu",
ref: blockActionsMenuPickerRef,
options: options,
onChange: onPickerSelect,
destructiveButtonIndex: options.length,
disabledButtonIndices: disabledButtonIndices,
hideCancelButton: _reactNative.Platform.OS !== 'ios',
leftAlign: true,
getAnchor: getAnchor
// translators: %s: block title e.g: "Paragraph".
,
title: (0, _i18n.sprintf)((0, _i18n.__)('%s block options'), blockTitle)
}), /*#__PURE__*/(0, _jsxRuntime.jsx)(_blockTransformationsMenu.default, {
anchorNodeRef: anchorNodeRef,
blockTitle: blockTitle,
pickerRef: blockTransformationMenuPickerRef,
possibleTransformations: selectedBlockPossibleTransformations,
selectedBlock: getBlocksByClientId(selectedBlockClientId),
selectedBlockClientId: selectedBlockClientId
})]
});
};
const EMPTY_BLOCK_LIST = [];
var _default = exports.default = (0, _compose.compose)((0, _data.withSelect)((select, {
clientId
}) => {
const {
getBlockIndex,
getBlockRootClientId,
getBlockOrder,
getBlockName,
getBlockTransformItems,
getBlock,
getBlocksByClientId,
getSelectedBlockClientIds,
canInsertBlockType,
getTemplateLock
} = select(_store.store);
const block = getBlock(clientId);
const blockName = getBlockName(clientId);
const blockType = (0, _blocks.getBlockType)(blockName);
const blockTitle = blockType?.title;
const rootClientId = getBlockRootClientId(clientId);
const blockOrder = getBlockOrder(rootClientId);
const currentBlockIndex = getBlockIndex(clientId);
const isFirst = currentBlockIndex === 0;
const isLast = currentBlockIndex === blockOrder.length - 1;
const innerBlocks = getBlocksByClientId(clientId);
const canDuplicate = innerBlocks.every(innerBlock => {
return !!innerBlock && (0, _blocks.hasBlockSupport)(innerBlock.name, 'multiple', true) && canInsertBlockType(innerBlock.name, rootClientId);
});
const isDefaultBlock = blockName === (0, _blocks.getDefaultBlockName)();
const isEmptyContent = block?.attributes.content === '';
const isExactlyOneBlock = blockOrder.length === 1;
const isEmptyDefaultBlock = isExactlyOneBlock && isDefaultBlock && isEmptyContent;
const isLocked = !!getTemplateLock(rootClientId);
const selectedBlockClientId = getSelectedBlockClientIds()[0];
const selectedBlock = selectedBlockClientId ? getBlocksByClientId(selectedBlockClientId)[0] : undefined;
const selectedBlockPossibleTransformations = selectedBlock ? getBlockTransformItems(selectedBlock, rootClientId) : EMPTY_BLOCK_LIST;
const isReusableBlockType = block ? (0, _blocks.isReusableBlock)(block) : false;
const reusableBlock = isReusableBlockType ? select(_coreData.store).getEntityRecord('postType', 'wp_block', block?.attributes.ref) : undefined;
return {
blockTitle,
canInsertBlockType,
currentIndex: currentBlockIndex,
getBlocksByClientId,
isEmptyDefaultBlock,
isLocked,
canDuplicate,
isFirst,
isLast,
isReusableBlockType,
reusableBlock,
rootClientId,
selectedBlockClientId,
selectedBlockPossibleTransformations
};
}), (0, _data.withDispatch)((dispatch, {
clientId,
rootClientId,
currentIndex,
selectedBlockClientId
}, {
select
}) => {
const {
moveBlocksDown,
moveBlocksUp,
duplicateBlocks,
removeBlocks,
insertBlock,
replaceBlock,
clearSelectedBlock
} = dispatch(_store.store);
const {
openGeneralSidebar
} = dispatch('core/edit-post');
const {
getBlockSelectionEnd,
getBlock
} = select(_store.store);
const {
createSuccessNotice
} = dispatch(_notices.store);
const {
__experimentalConvertBlockToStatic: convertBlockToStatic
} = dispatch(_reusableBlocks.store);
return {
createSuccessNotice,
convertToRegularBlocks() {
clearSelectedBlock();
// Convert action is executed at the end of the current JavaScript execution block
// to prevent issues related to undo/redo actions.
setImmediate(() => convertBlockToStatic(selectedBlockClientId));
},
duplicateBlock() {
return duplicateBlocks([clientId]);
},
onMoveDown: (...args) => moveBlocksDown([clientId], rootClientId, ...args),
onMoveUp: (...args) => moveBlocksUp([clientId], rootClientId, ...args),
openGeneralSidebar: () => openGeneralSidebar('edit-post/block'),
pasteBlock: clipboardBlock => {
const canReplaceBlock = (0, _blocks.isUnmodifiedDefaultBlock)(getBlock(getBlockSelectionEnd()));
if (!canReplaceBlock) {
const insertedBlock = (0, _blocks.createBlock)(clipboardBlock.name, clipboardBlock.attributes, clipboardBlock.innerBlocks);
insertBlock(insertedBlock, currentIndex + 1, rootClientId);
} else {
replaceBlock(clientId, clipboardBlock);
}
},
removeBlocks
};
}), _compose.withInstanceId)(BlockActionsMenu);
//# sourceMappingURL=block-toolbar-menu.native.js.map
;