@gechiui/block-editor
Version:
218 lines (206 loc) • 5.59 kB
JavaScript
/**
* External dependencies
*/
import { castArray, flow, noop } from 'lodash';
/**
* GeChiUI dependencies
*/
import { __, sprintf } from '@gechiui/i18n';
import { DropdownMenu, MenuGroup, MenuItem } from '@gechiui/components';
import { useSelect } from '@gechiui/data';
import { moreVertical } from '@gechiui/icons';
import { Children, cloneElement, useCallback } from '@gechiui/element';
import { serialize, store as blocksStore } from '@gechiui/blocks';
import { store as keyboardShortcutsStore } from '@gechiui/keyboard-shortcuts';
import { useCopyToClipboard } from '@gechiui/compose';
/**
* Internal dependencies
*/
import BlockActions from '../block-actions';
import BlockModeToggle from './block-mode-toggle';
import BlockHTMLConvertButton from './block-html-convert-button';
import __unstableBlockSettingsMenuFirstItem from './block-settings-menu-first-item';
import BlockSettingsMenuControls from '../block-settings-menu-controls';
import { store as blockEditorStore } from '../../store';
const POPOVER_PROPS = {
className: 'block-editor-block-settings-menu__popover',
position: 'bottom right',
isAlternate: true,
};
function CopyMenuItem( { blocks, onCopy } ) {
const ref = useCopyToClipboard( () => serialize( blocks ), onCopy );
return <MenuItem ref={ ref }>{ __( '复制' ) }</MenuItem>;
}
export function BlockSettingsDropdown( {
clientIds,
__experimentalSelectBlock,
children,
...props
} ) {
const blockClientIds = castArray( clientIds );
const count = blockClientIds.length;
const firstBlockClientId = blockClientIds[ 0 ];
const { onlyBlock, title } = useSelect(
( select ) => {
const { getBlockCount, getBlockName } = select( blockEditorStore );
const { getBlockType } = select( blocksStore );
return {
onlyBlock: 1 === getBlockCount(),
title: getBlockType( getBlockName( firstBlockClientId ) )
?.title,
};
},
[ firstBlockClientId ]
);
const shortcuts = useSelect( ( select ) => {
const { getShortcutRepresentation } = select( keyboardShortcutsStore );
return {
duplicate: getShortcutRepresentation(
'core/block-editor/duplicate'
),
remove: getShortcutRepresentation( 'core/block-editor/remove' ),
insertAfter: getShortcutRepresentation(
'core/block-editor/insert-after'
),
insertBefore: getShortcutRepresentation(
'core/block-editor/insert-before'
),
};
}, [] );
const updateSelection = useCallback(
__experimentalSelectBlock
? async ( clientIdsPromise ) => {
const ids = await clientIdsPromise;
if ( ids && ids[ 0 ] ) {
__experimentalSelectBlock( ids[ 0 ] );
}
}
: noop,
[ __experimentalSelectBlock ]
);
const label = sprintf(
/* translators: %s: block name */
__( '删除 %s' ),
title
);
const removeBlockLabel = count === 1 ? label : __( '移除区块' );
return (
<BlockActions
clientIds={ clientIds }
__experimentalUpdateSelection={ ! __experimentalSelectBlock }
>
{ ( {
canDuplicate,
canInsertDefaultBlock,
canMove,
canRemove,
onDuplicate,
onInsertAfter,
onInsertBefore,
onRemove,
onCopy,
onMoveTo,
blocks,
} ) => (
<DropdownMenu
icon={ moreVertical }
label={ __( '选项' ) }
className="block-editor-block-settings-menu"
popoverProps={ POPOVER_PROPS }
noIcons
{ ...props }
>
{ ( { onClose } ) => (
<>
<MenuGroup>
<__unstableBlockSettingsMenuFirstItem.Slot
fillProps={ { onClose } }
/>
{ count === 1 && (
<BlockHTMLConvertButton
clientId={ firstBlockClientId }
/>
) }
<CopyMenuItem
blocks={ blocks }
onCopy={ onCopy }
/>
{ canDuplicate && (
<MenuItem
onClick={ flow(
onClose,
onDuplicate,
updateSelection
) }
shortcut={ shortcuts.duplicate }
>
{ __( '创建副本' ) }
</MenuItem>
) }
{ canInsertDefaultBlock && (
<>
<MenuItem
onClick={ flow(
onClose,
onInsertBefore
) }
shortcut={ shortcuts.insertBefore }
>
{ __( '在当前区块前插入' ) }
</MenuItem>
<MenuItem
onClick={ flow(
onClose,
onInsertAfter
) }
shortcut={ shortcuts.insertAfter }
>
{ __( '在当前区块后插入' ) }
</MenuItem>
</>
) }
{ canMove && ! onlyBlock && (
<MenuItem
onClick={ flow( onClose, onMoveTo ) }
>
{ __( '移动至' ) }
</MenuItem>
) }
{ count === 1 && (
<BlockModeToggle
clientId={ firstBlockClientId }
onToggle={ onClose }
/>
) }
</MenuGroup>
<BlockSettingsMenuControls.Slot
fillProps={ { onClose } }
clientIds={ clientIds }
/>
{ typeof children === 'function'
? children( { onClose } )
: Children.map( ( child ) =>
cloneElement( child, { onClose } )
) }
{ canRemove && (
<MenuGroup>
<MenuItem
onClick={ flow(
onClose,
onRemove,
updateSelection
) }
shortcut={ shortcuts.remove }
>
{ removeBlockLabel }
</MenuItem>
</MenuGroup>
) }
</>
) }
</DropdownMenu>
) }
</BlockActions>
);
}
export default BlockSettingsDropdown;