diff --git a/packages/block-editor/src/components/block-list/block-list-item.native.js b/packages/block-editor/src/components/block-list/block-list-item.native.js index ef6bbbe1ffc3ce..f1885196f67f75 100644 --- a/packages/block-editor/src/components/block-list/block-list-item.native.js +++ b/packages/block-editor/src/components/block-list/block-list-item.native.js @@ -1,246 +1,209 @@ /** * External dependencies */ -import { View, Dimensions } from 'react-native'; +import { View } from 'react-native'; /** * WordPress dependencies */ -import { Component } from '@wordpress/element'; -import { withSelect } from '@wordpress/data'; -import { compose } from '@wordpress/compose'; -import { ReadableContentView, alignmentHelpers } from '@wordpress/components'; +import { useSelect } from '@wordpress/data'; /** * Internal dependencies */ -import BlockListBlock from './block'; -import BlockInsertionPoint from './insertion-point'; +import Block from './block'; import Grid from './grid-item'; - -import styles from './block-list-item.native.scss'; +import BlockInsertionPoint from './insertion-point'; import { store as blockEditorStore } from '../../store'; +import { useEditorWrapperStyles } from '../../hooks/use-editor-wrapper-styles'; -const stretchStyle = { - flex: 1, -}; - -export class BlockListItem extends Component { - getMarginHorizontal() { - const { - blockAlignment, - marginHorizontal, - parentBlockAlignment, - hasParents, - blockName, - parentBlockName, - parentWidth, - blockWidth, - } = this.props; - const { isFullWidth, isWideWidth, isWider, isContainerRelated } = - alignmentHelpers; - - if ( isFullWidth( blockAlignment ) ) { - if ( ! hasParents ) { - return 0; - } - return marginHorizontal; - } - if ( isWideWidth( blockAlignment ) ) { - return marginHorizontal; - } - - const screenWidth = Math.floor( Dimensions.get( 'window' ).width ); - - if ( - isFullWidth( parentBlockAlignment ) && - ! isWider( blockWidth, 'medium' ) - ) { - if ( - isContainerRelated( blockName ) || - isWider( screenWidth, 'mobile' ) - ) { - return marginHorizontal; - } - return marginHorizontal * 2; - } - - if ( - isContainerRelated( parentBlockName ) && - ! isContainerRelated( blockName ) - ) { - const isScreenWidthEqual = parentWidth === screenWidth; - if ( isScreenWidthEqual || isWider( screenWidth, 'mobile' ) ) { - return marginHorizontal; - } - } - - return marginHorizontal; - } - - getContentStyles( readableContentViewStyle ) { - const { blockAlignment, blockName, hasParents, parentBlockName } = - this.props; - const { isFullWidth, isContainerRelated } = alignmentHelpers; - - return [ - readableContentViewStyle, - isFullWidth( blockAlignment ) && - ! hasParents && { - width: styles.fullAlignment.width, - }, - ! blockAlignment && - hasParents && - ! isContainerRelated( parentBlockName ) && - isContainerRelated( blockName ) && { - paddingHorizontal: styles.fullAlignmentPadding.paddingLeft, - }, - ]; - } - - renderContent() { - const { - blockAlignment, - clientId, - index, - isReadOnly, - shouldShowInsertionPointBefore, - shouldShowInsertionPointAfter, - contentResizeMode, - shouldShowInnerBlockAppender, - parentWidth, - marginHorizontal, - blockName, - blockWidth, - ...restProps - } = this.props; - - const readableContentViewStyle = - contentResizeMode === 'stretch' && stretchStyle; - const { isContainerRelated } = alignmentHelpers; - - return ( - - - { shouldShowInsertionPointBefore && ( - - ) } - - { ! shouldShowInnerBlockAppender() && - shouldShowInsertionPointAfter && ( - - ) } - - - ); - } - - render() { - const { parentWidth, blockWidth, isGridItem } = this.props; - - if ( ! blockWidth ) { - return null; - } - - if ( isGridItem ) { - const { numOfColumns, tileCount, tileIndex } = this.props; - return ( - - { this.renderContent() } - - ); - } - return this.renderContent(); - } -} - -export default compose( [ - withSelect( - ( select, { rootClientId, isStackedHorizontally, clientId } ) => { +/** + * BlockListItemContent component. Renders a block with an optional insertion point. + * + * @param {Object} props Component properties. + * @param {number} props.blockWidth The width of the block. + * @param {string} props.clientId The block client ID. + * @param {string} props.contentResizeMode The content resize mode, e.g "stretch". + * @param {Object} props.contentStyle Styles for the block content + * @param {Object} props.index Block item index + * @param {boolean} props.isStackedHorizontally Whether the block is stacked horizontally. + * @param {number} props.marginHorizontal The horizontal margin. + * @param {number} props.marginVertical The vertical margin. + * @param {Function} props.onAddBlock On add block callback. + * @param {Function} props.onDeleteBlock On delete block callback. + * @param {number} props.parentWidth The width of the parent block. + * @param {string} props.rootClientId The root client ID. + * @param {Function} props.shouldShowInnerBlockAppender Whether to show the inner block appender. + * + * @return {WPComponent} The rendered block list item content. + */ +function BlockListItemContent( { + blockWidth, + clientId, + contentResizeMode, + contentStyle, + index, + isStackedHorizontally, + marginHorizontal, + marginVertical, + onAddBlock, + onDeleteBlock, + parentWidth, + rootClientId, + shouldShowInnerBlockAppender, +} ) { + const { + blockAlignment, + blockName, + hasParents, + parentBlockAlignment, + parentBlockName, + shouldShowInsertionPointAfter, + shouldShowInsertionPointBefore, + } = useSelect( + ( select ) => { const { - getBlockOrder, + getBlockAttributes, getBlockInsertionPoint, + getBlockName, + getBlockOrder, isBlockInsertionPointVisible, - getSettings, - getBlockParents, - getBlock, } = select( blockEditorStore ); - const blockClientIds = getBlockOrder( rootClientId ); const insertionPoint = getBlockInsertionPoint(); - const blockInsertionPointIsVisible = isBlockInsertionPointVisible(); - const shouldShowInsertionPointBefore = - ! isStackedHorizontally && - blockInsertionPointIsVisible && - insertionPoint.rootClientId === rootClientId && - // If list is empty, show the insertion point (via the default appender) - ( blockClientIds.length === 0 || - // Or if the insertion point is right before the denoted block. - blockClientIds[ insertionPoint.index ] === clientId ); - - const shouldShowInsertionPointAfter = + + const insertionPointVisibleInCurrentRoot = ! isStackedHorizontally && - blockInsertionPointIsVisible && - insertionPoint.rootClientId === rootClientId && - // If the insertion point is at the end of the list. - blockClientIds.length === insertionPoint.index && - // And the denoted block is the last one on the list, show the indicator at the end of the block. + isBlockInsertionPointVisible() && + insertionPoint.rootClientId === rootClientId; + + const isListEmpty = blockClientIds.length === 0; + const isInsertionPointBeforeBlock = + blockClientIds[ insertionPoint.index ] === clientId; + const isInsertionPointAtEnd = + blockClientIds.length === insertionPoint.index; + const isBlockLastInList = blockClientIds[ insertionPoint.index - 1 ] === clientId; - const isReadOnly = getSettings().readOnly; + const showInsertionPointBefore = + insertionPointVisibleInCurrentRoot && + ( isListEmpty || isInsertionPointBeforeBlock ); + + const showInsertionPointAfter = + insertionPointVisibleInCurrentRoot && + isInsertionPointAtEnd && + isBlockLastInList; - const { attributes, name } = getBlock( clientId ) || {}; - const { align } = attributes || {}; - const parents = getBlockParents( clientId, true ); - const hasParents = !! parents.length; - const parentBlock = hasParents ? getBlock( parents[ 0 ] ) : {}; - const { align: parentBlockAlignment } = - parentBlock?.attributes || {}; - const { name: parentBlockName } = parentBlock || {}; + const blockHasParents = !! rootClientId; + const name = getBlockName( clientId ); + const parentName = getBlockName( rootClientId ); + const { align } = getBlockAttributes( clientId ) || {}; + const { align: parentBlockAlign } = + getBlockAttributes( rootClientId ) || {}; return { - shouldShowInsertionPointBefore, - shouldShowInsertionPointAfter, - isReadOnly, - hasParents, blockAlignment: align, - parentBlockAlignment, blockName: name, - parentBlockName, + hasParents: blockHasParents, + parentBlockAlignment: parentBlockAlign, + parentBlockName: parentName, + shouldShowInsertionPointAfter: showInsertionPointAfter, + shouldShowInsertionPointBefore: showInsertionPointBefore, }; - } - ), -] )( BlockListItem ); + }, + [ isStackedHorizontally, rootClientId, clientId ] + ); + + const [ wrapperStyles, margin ] = useEditorWrapperStyles( { + align: blockAlignment, + blockName, + blockWidth, + contentResizeMode, + hasParents, + marginHorizontal, + parentBlockAlignment, + parentBlockName, + parentWidth, + } ); + + const shouldShowBlockInsertionPointAfter = + ! shouldShowInnerBlockAppender() && shouldShowInsertionPointAfter; + + return ( + + { shouldShowInsertionPointBefore && ( + + ) } + + { shouldShowBlockInsertionPointAfter && ( + + ) } + + ); +} + +/** + * BlockListItem component. Renders a block list item either as a grid item or as a standalone item. + * + * @param {Object} props Component properties. + * @param {boolean} props.isGridItem Whether the block is a grid item. + * @param {number} props.numOfColumns The number of columns for grid layout. + * @param {number} props.parentWidth The width of the parent block. + * @param {number} props.tileCount The total number of tiles in the grid. + * @param {number} props.tileIndex The index of the current tile in the grid. + * @param {number} props.blockWidth The width of the block. + * @param {string} props.clientId The block client ID. + * @param {string} props.contentResizeMode The content resize mode, e.g "stretch". + * @param {Object} props.contentStyle Styles for the block content + * @param {Object} props.index Block item index + * @param {boolean} props.isStackedHorizontally Whether the block is stacked horizontally. + * @param {number} props.marginHorizontal The horizontal margin. + * @param {number} props.marginVertical The vertical margin. + * @param {Function} props.onAddBlock On add block callback. + * @param {Function} props.onDeleteBlock On delete block callback. + * @param {string} props.rootClientId The root client ID. + * @param {Function} props.shouldShowInnerBlockAppender Whether to show the inner block appender. + * + * @return {WPComponent|null} The rendered block list item or null if the block width is not provided. + */ +function BlockListItem( props ) { + const { isGridItem, numOfColumns, tileCount, tileIndex, ...restProps } = + props; + + if ( ! props?.blockWidth ) { + return null; + } + + if ( isGridItem ) { + return ( + + + + ); + } + + return ; +} + +export default BlockListItem;