UNPKG

@wordpress/block-editor

Version:
194 lines (177 loc) 4.91 kB
/** * External dependencies */ import { Platform } from 'react-native'; /** * WordPress dependencies */ import { __ } from '@wordpress/i18n'; import { Picker, ToolbarButton, ToolbarGroup } from '@wordpress/components'; import { withInstanceId, compose } from '@wordpress/compose'; import { withSelect, withDispatch } from '@wordpress/data'; import { useCallback, useEffect, useRef, useState } from '@wordpress/element'; /** * Internal dependencies */ import { getMoversSetup } from './mover-description'; import { store as blockEditorStore } from '../../store'; export const BLOCK_MOVER_DIRECTION_TOP = 'blockPageMoverOptions-moveToTop'; export const BLOCK_MOVER_DIRECTION_BOTTOM = 'blockPageMoverOptions-moveToBottom'; export const BlockMover = ( { isFirst, isLast, canMove, onMoveDown, onMoveUp, onLongMove, firstIndex, numberOfBlocks, rootClientId, isStackedHorizontally, } ) => { const pickerRef = useRef(); const [ shouldPresentPicker, setShouldPresentPicker ] = useState( false ); const [ blockPageMoverState, setBlockPageMoverState ] = useState( undefined ); const showBlockPageMover = ( direction ) => () => { if ( ! pickerRef.current ) { setBlockPageMoverState( undefined ); return; } setBlockPageMoverState( direction ); setShouldPresentPicker( true ); }; // Ensure that the picker is only presented after state updates. useEffect( () => { if ( shouldPresentPicker ) { pickerRef.current?.presentPicker(); setShouldPresentPicker( false ); } }, [ shouldPresentPicker ] ); const { description: { backwardButtonHint, forwardButtonHint, firstBlockTitle, lastBlockTitle, }, icon: { backward: backwardButtonIcon, forward: forwardButtonIcon }, title: { backward: backwardButtonTitle, forward: forwardButtonTitle }, } = getMoversSetup( isStackedHorizontally, { firstIndex } ); const blockPageMoverOptions = [ { icon: backwardButtonIcon, label: __( 'Move to top' ), value: BLOCK_MOVER_DIRECTION_TOP, onSelect: () => { onLongMove()( 0 ); }, }, { icon: forwardButtonIcon, label: __( 'Move to bottom' ), value: BLOCK_MOVER_DIRECTION_BOTTOM, onSelect: () => { onLongMove()( numberOfBlocks ); }, }, ].filter( ( el ) => el.value === blockPageMoverState ); const onPickerSelect = ( value ) => { const option = blockPageMoverOptions.find( ( el ) => el.value === value ); if ( option && option.onSelect ) { option.onSelect(); } }; const onLongPressMoveUp = useCallback( showBlockPageMover( BLOCK_MOVER_DIRECTION_TOP ), [] ); const onLongPressMoveDown = useCallback( showBlockPageMover( BLOCK_MOVER_DIRECTION_BOTTOM ), [] ); if ( ! canMove || ( isFirst && isLast && ! rootClientId ) ) { return null; } return ( <ToolbarGroup> <ToolbarButton title={ ! isFirst ? backwardButtonTitle : firstBlockTitle } isDisabled={ isFirst } onClick={ onMoveUp } onLongPress={ onLongPressMoveUp } icon={ backwardButtonIcon } extraProps={ { hint: backwardButtonHint } } /> <ToolbarButton title={ ! isLast ? forwardButtonTitle : lastBlockTitle } isDisabled={ isLast } onClick={ onMoveDown } onLongPress={ onLongPressMoveDown } icon={ forwardButtonIcon } extraProps={ { hint: forwardButtonHint, } } /> <Picker ref={ pickerRef } options={ blockPageMoverOptions } onChange={ onPickerSelect } title={ __( 'Change block position' ) } leftAlign hideCancelButton={ Platform.OS !== 'ios' } /> </ToolbarGroup> ); }; export default compose( withSelect( ( select, { clientIds } ) => { const { getBlockIndex, canMoveBlocks, getBlockRootClientId, getBlockOrder, } = select( blockEditorStore ); const normalizedClientIds = Array.isArray( clientIds ) ? clientIds : [ clientIds ]; const firstClientId = normalizedClientIds[ 0 ]; const rootClientId = getBlockRootClientId( firstClientId ); const blockOrder = getBlockOrder( rootClientId ); const firstIndex = getBlockIndex( firstClientId ); const lastIndex = getBlockIndex( normalizedClientIds[ normalizedClientIds.length - 1 ] ); return { firstIndex, numberOfBlocks: blockOrder.length - 1, isFirst: firstIndex === 0, isLast: lastIndex === blockOrder.length - 1, canMove: canMoveBlocks( clientIds ), rootClientId, }; } ), withDispatch( ( dispatch, { clientIds, rootClientId } ) => { const { moveBlocksDown, moveBlocksUp, moveBlocksToPosition } = dispatch( blockEditorStore ); return { onMoveDown: ( ...args ) => moveBlocksDown( clientIds, rootClientId, ...args ), onMoveUp: ( ...args ) => moveBlocksUp( clientIds, rootClientId, ...args ), onLongMove: ( targetIndex ) => ( ...args ) => moveBlocksToPosition( clientIds, rootClientId, targetIndex, ...args ), }; } ), withInstanceId )( BlockMover );