diff --git a/lib/experiments-page.php b/lib/experiments-page.php index 8604c80ab7d2b7..224f058edaddfe 100644 --- a/lib/experiments-page.php +++ b/lib/experiments-page.php @@ -58,7 +58,7 @@ function gutenberg_initialize_experiments_settings() { 'gutenberg-experiments', 'gutenberg_experiments_section', array( - 'label' => __( 'Test a new gallery block that uses nested image blocks', 'gutenberg' ), + 'label' => __( 'Test a new gallery block that uses nested image blocks (Warning: The new gallery is not compatible with WordPress mobile apps prior to version 18.1. If you use the mobile app, please update to the latest version to avoid content loss.)', 'gutenberg' ), 'id' => 'gutenberg-gallery-refactor', ) ); 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 d1d50a3c3a1f7d..fae95956fa735a 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 @@ -16,6 +16,8 @@ import { ReadableContentView, alignmentHelpers } from '@wordpress/components'; */ import BlockListBlock from './block'; import BlockInsertionPoint from './insertion-point'; +import Grid from './grid-item'; + import styles from './block-list-item.native.scss'; import { store as blockEditorStore } from '../../store'; @@ -104,7 +106,7 @@ export class BlockListItem extends Component { ]; } - render() { + renderContent() { const { blockAlignment, clientId, @@ -123,10 +125,6 @@ export class BlockListItem extends Component { contentResizeMode === 'stretch' && stretchStyle; const { isContainerRelated } = alignmentHelpers; - if ( ! blockWidth ) { - return null; - } - return ( ); } + + render() { + const { + gridProperties, + clientId, + parentWidth, + items, + blockWidth, + } = this.props; + + if ( ! blockWidth ) { + return null; + } + + if ( gridProperties ) { + return ( + + { this.renderContent() } + + ); + } + return this.renderContent(); + } } export default compose( [ diff --git a/packages/block-editor/src/components/block-list/block-list-item.native.scss b/packages/block-editor/src/components/block-list/block-list-item.native.scss index 8e2eca61430341..82baa74a07111a 100644 --- a/packages/block-editor/src/components/block-list/block-list-item.native.scss +++ b/packages/block-editor/src/components/block-list/block-list-item.native.scss @@ -10,3 +10,7 @@ .fullAlignmentPadding { padding: $block-edge-to-content; } + +.gridItem { + overflow: visible; +} diff --git a/packages/block-editor/src/components/block-list/grid-item.native.js b/packages/block-editor/src/components/block-list/grid-item.native.js new file mode 100644 index 00000000000000..053b3ecfe90d5d --- /dev/null +++ b/packages/block-editor/src/components/block-list/grid-item.native.js @@ -0,0 +1,58 @@ +/** + * External dependencies + */ +import { View } from 'react-native'; + +/** + * Internal dependencies + */ +import styles from './block-list-item.scss'; + +function Grid( props ) { + /** + * Since we don't have `calc()`, we must calculate our spacings here in + * order to preserve even spacing between tiles and equal width for tiles + * in a given row. + * + * In order to ensure equal sizing of tile contents, we distribute the + * spacing such that each tile has an equal "share" of the fixed spacing. To + * keep the tiles properly aligned within their rows, we calculate the left + * and right paddings based on the tile's relative position within the row. + * + * Note: we use padding instead of margins so that the fixed spacing is + * included within the relative spacing (i.e. width percentage), and + * wrapping behavior is preserved. + * + * - The left most tile in a row must have left padding of zero. + * - The right most tile in a row must have a right padding of zero. + * + * The values of these left and right paddings are interpolated for tiles in + * between. The right padding is complementary with the left padding of the + * next tile (i.e. the right padding of [tile n] + the left padding of + * [tile n + 1] will be equal for all tiles except the last one in a given + * row). + * + */ + const { numOfColumns, children, tileCount, index, maxWidth } = props; + const lastTile = tileCount - 1; + const lastRow = Math.floor( lastTile / numOfColumns ); + + const row = Math.floor( index / numOfColumns ); + const rowLength = + row === lastRow ? ( lastTile % numOfColumns ) + 1 : numOfColumns; + + return ( + + { children } + + ); +} + +export default Grid; diff --git a/packages/block-editor/src/components/block-list/index.native.js b/packages/block-editor/src/components/block-list/index.native.js index fec28608b04641..4ce520ed818751 100644 --- a/packages/block-editor/src/components/block-list/index.native.js +++ b/packages/block-editor/src/components/block-list/index.native.js @@ -47,6 +47,7 @@ const getStyles = ( const computedStyles = [ isStackedHorizontally && styles.horizontal, horizontalAlignment && styles[ `is-aligned-${ horizontalAlignment }` ], + styles.overflowVisible, ]; stylesMemo[ styleName ] = computedStyles; return computedStyles; @@ -128,6 +129,7 @@ export class BlockList extends Component { onDeleteBlock, contentStyle, renderAppender, + gridProperties, } = this.props; const { blockWidth } = this.state; if ( @@ -136,7 +138,8 @@ export class BlockList extends Component { this.extraData.onDeleteBlock !== onDeleteBlock || this.extraData.contentStyle !== contentStyle || this.extraData.renderAppender !== renderAppender || - this.extraData.blockWidth !== blockWidth + this.extraData.blockWidth !== blockWidth || + this.extraData.gridProperties !== gridProperties ) { this.extraData = { parentWidth, @@ -145,6 +148,7 @@ export class BlockList extends Component { contentStyle, renderAppender, blockWidth, + gridProperties, }; } return this.extraData; @@ -312,9 +316,11 @@ export class BlockList extends Component { onDeleteBlock, rootClientId, isStackedHorizontally, + blockClientIds, parentWidth, marginVertical = styles.defaultBlock.marginTop, marginHorizontal = styles.defaultBlock.marginLeft, + gridProperties, } = this.props; const { blockWidth } = this.state; return ( @@ -333,6 +339,8 @@ export class BlockList extends Component { this.shouldShowInnerBlockAppender } blockWidth={ blockWidth } + gridProperties={ gridProperties } + items={ blockClientIds } /> ); } diff --git a/packages/block-editor/src/components/block-styles/preview.native.js b/packages/block-editor/src/components/block-styles/preview.native.js index c5461bf330acb9..c017331ad38a32 100644 --- a/packages/block-editor/src/components/block-styles/preview.native.js +++ b/packages/block-editor/src/components/block-styles/preview.native.js @@ -71,7 +71,7 @@ function StylePreview( { onPress, isActive, style, url } ) { return ( ); } ); diff --git a/packages/block-editor/src/components/index.native.js b/packages/block-editor/src/components/index.native.js index b3617e95ef63eb..89fa80d8b44c83 100644 --- a/packages/block-editor/src/components/index.native.js +++ b/packages/block-editor/src/components/index.native.js @@ -18,7 +18,10 @@ export * from './colors'; export * from './gradients'; export * from './font-sizes'; export { AlignmentControl, AlignmentToolbar } from './alignment-control'; -export { default as InnerBlocks } from './inner-blocks'; +export { + default as InnerBlocks, + useInnerBlocksProps as __experimentalUseInnerBlocksProps, +} from './inner-blocks'; export { default as InspectorAdvancedControls } from './inspector-advanced-controls'; export { default as InspectorControls } from './inspector-controls'; export { diff --git a/packages/block-editor/src/components/inner-blocks/index.native.js b/packages/block-editor/src/components/inner-blocks/index.native.js index 0b9401425e8640..e1b87087fcbebb 100644 --- a/packages/block-editor/src/components/inner-blocks/index.native.js +++ b/packages/block-editor/src/components/inner-blocks/index.native.js @@ -3,6 +3,7 @@ */ import { useSelect } from '@wordpress/data'; import { getBlockType, withBlockContentContext } from '@wordpress/blocks'; +import { useRef } from '@wordpress/element'; /** * Internal dependencies @@ -23,6 +24,44 @@ import { BlockContextProvider } from '../block-context'; import { defaultLayout, LayoutProvider } from '../block-list/layout'; import { store as blockEditorStore } from '../../store'; +/** + * This hook is used to lightly mark an element as an inner blocks wrapper + * element. Call this hook and pass the returned props to the element to mark as + * an inner blocks wrapper, automatically rendering inner blocks as children. If + * you define a ref for the element, it is important to pass the ref to this + * hook, which the hook in turn will pass to the component through the props it + * returns. Optionally, you can also pass any other props through this hook, and + * they will be merged and returned. + * + * @param {Object} props Optional. Props to pass to the element. Must contain + * the ref if one is defined. + * @param {Object} options Optional. Inner blocks options. + * + * @see https://github.com/WordPress/gutenberg/blob/master/packages/block-editor/src/components/inner-blocks/README.md + */ +export function useInnerBlocksProps( props = {}, options = {} ) { + const fallbackRef = useRef(); + const { clientId } = useBlockEditContext(); + + const ref = props.ref || fallbackRef; + const InnerBlocks = + options.value && options.onChange + ? ControlledInnerBlocks + : UncontrolledInnerBlocks; + + return { + ...props, + ref, + children: ( + + ), + }; +} + /** * InnerBlocks is a component which allows a single block to have multiple blocks * as children. The UncontrolledInnerBlocks component is used whenever the inner @@ -53,6 +92,7 @@ function UncontrolledInnerBlocks( props ) { filterInnerBlocks, blockWidth, __experimentalLayout: layout = defaultLayout, + gridProperties, } = props; const block = useSelect( @@ -86,6 +126,7 @@ function UncontrolledInnerBlocks( props ) { onAddBlock={ onAddBlock } onDeleteBlock={ onDeleteBlock } filterInnerBlocks={ filterInnerBlocks } + gridProperties={ gridProperties } blockWidth={ blockWidth } /> ); diff --git a/packages/block-editor/src/components/media-placeholder/index.native.js b/packages/block-editor/src/components/media-placeholder/index.native.js index 24b826c8c8f9e1..ed9b43e5ada567 100644 --- a/packages/block-editor/src/components/media-placeholder/index.native.js +++ b/packages/block-editor/src/components/media-placeholder/index.native.js @@ -38,6 +38,7 @@ function MediaPlaceholder( props ) { labels = {}, icon, onSelect, + onFocus, __experimentalOnlyMediaLibrary, isAppender, disableMediaButtons, @@ -175,7 +176,7 @@ function MediaPlaceholder( props ) { accessibilityRole={ 'button' } accessibilityHint={ accessibilityHint } onPress={ ( event ) => { - props.onFocus( event ); + onFocus?.( event ); open(); } } > diff --git a/packages/block-editor/src/store/defaults.native.js b/packages/block-editor/src/store/defaults.native.js index 125ee6c85c1f42..7bacdee31ef5e8 100644 --- a/packages/block-editor/src/store/defaults.native.js +++ b/packages/block-editor/src/store/defaults.native.js @@ -8,6 +8,9 @@ import { const SETTINGS_DEFAULTS = { ...SETTINGS, + // FOR TESTING ONLY - Later, this will come from a REST API + // eslint-disable-next-line no-undef + __unstableGalleryWithImageBlocks: __DEV__, alignWide: true, }; diff --git a/packages/block-library/src/gallery/edit.js b/packages/block-library/src/gallery/edit.js index d51329fc6bbf93..3a1fa9c990b952 100644 --- a/packages/block-library/src/gallery/edit.js +++ b/packages/block-library/src/gallery/edit.js @@ -61,17 +61,13 @@ const linkOptions = [ ]; const ALLOWED_MEDIA_TYPES = [ 'image' ]; -const PLACEHOLDER_TEXT = Platform.select( { - web: __( - 'Drag images, upload new ones or select files from your library.' - ), - native: __( 'ADD MEDIA' ), -} ); - -const MOBILE_CONTROL_PROPS_RANGE_CONTROL = Platform.select( { - web: {}, - native: { type: 'stepper' }, -} ); +const PLACEHOLDER_TEXT = Platform.isNative + ? __( 'ADD MEDIA' ) + : __( 'Drag images, upload new ones or select files from your library.' ); + +const MOBILE_CONTROL_PROPS_RANGE_CONTROL = Platform.isNative + ? { type: 'stepper' } + : {}; function GalleryEdit( props ) { const { @@ -491,7 +487,7 @@ function GalleryEdit( props ) { hideCancelButton={ true } /> ) } - { ! imageSizeOptions && ( + { Platform.isWeb && ! imageSizeOptions && ( { __( 'Image size' ) } diff --git a/packages/block-library/src/gallery/gallery-styles.native.scss b/packages/block-library/src/gallery/gallery-styles.native.scss index 9b3169da048b22..a3073592291b93 100644 --- a/packages/block-library/src/gallery/gallery-styles.native.scss +++ b/packages/block-library/src/gallery/gallery-styles.native.scss @@ -1,5 +1,7 @@ -.galleryTilesContainerSelected { - margin-bottom: 16px; +@import "./v1/gallery-styles.native.scss"; + +.galleryAppender { + padding-top: $grid-unit-20; } .fullWidth { diff --git a/packages/block-library/src/gallery/gallery.native.js b/packages/block-library/src/gallery/gallery.native.js index 8a58e1f9ca3385..6dc9399747aae4 100644 --- a/packages/block-library/src/gallery/gallery.native.js +++ b/packages/block-library/src/gallery/gallery.native.js @@ -7,10 +7,8 @@ import { isEmpty } from 'lodash'; /** * Internal dependencies */ -import GalleryImage from './gallery-image'; import { defaultColumnsNumber } from './shared'; import styles from './gallery-styles.scss'; -import Tiles from './tiles'; /** * WordPress dependencies @@ -18,123 +16,88 @@ import Tiles from './tiles'; import { __, sprintf } from '@wordpress/i18n'; import { BlockCaption, - store as blockEditorStore, + __experimentalUseInnerBlocksProps as useInnerBlocksProps, } from '@wordpress/block-editor'; import { useState, useEffect } from '@wordpress/element'; import { mediaUploadSync } from '@wordpress/react-native-bridge'; -import { useSelect } from '@wordpress/data'; -import { alignmentHelpers } from '@wordpress/components'; +import { WIDE_ALIGNMENTS } from '@wordpress/components'; +import { useResizeObserver } from '@wordpress/compose'; -const TILE_SPACING = 15; +const TILE_SPACING = 8; // we must limit displayed columns since readable content max-width is 580px const MAX_DISPLAYED_COLUMNS = 4; const MAX_DISPLAYED_COLUMNS_NARROW = 2; -const { isFullWidth } = alignmentHelpers; - export const Gallery = ( props ) => { const [ isCaptionSelected, setIsCaptionSelected ] = useState( false ); + const [ resizeObserver, sizes ] = useResizeObserver(); + const [ maxWidth, setMaxWidth ] = useState( 0 ); useEffect( mediaUploadSync, [] ); - const isRTL = useSelect( ( select ) => { - return !! select( blockEditorStore ).getSettings().isRTL; - }, [] ); - const { - clientId, - selectedImage, mediaPlaceholder, - onBlur, - onMoveBackward, - onMoveForward, - onRemoveImage, - onSelectImage, - onSetImageAttributes, - onFocusGalleryCaption, attributes, - isSelected, isNarrow, - onFocus, + onBlur, insertBlocksAfter, + clientId, } = props; + useEffect( () => { + const { width } = sizes || {}; + if ( width ) { + setMaxWidth( width ); + } + }, [ sizes ] ); + const { - align, - columns = defaultColumnsNumber( attributes ), - imageCrop, images, + align, + columns = defaultColumnsNumber( images.length ), } = attributes; - // limit displayed columns when isNarrow is true (i.e. when viewport width is - // less than "small", where small = 600) - const displayedColumns = isNarrow - ? Math.min( columns, MAX_DISPLAYED_COLUMNS_NARROW ) - : Math.min( columns, MAX_DISPLAYED_COLUMNS ); + const displayedColumns = Math.min( + columns, + isNarrow ? MAX_DISPLAYED_COLUMNS_NARROW : MAX_DISPLAYED_COLUMNS + ); - const selectImage = ( index ) => { - return () => { - if ( isCaptionSelected ) { - setIsCaptionSelected( false ); - } - // we need to fully invoke the curried function here - onSelectImage( index )(); - }; - }; + const innerBlocksProps = useInnerBlocksProps( + {}, + { + contentResizeMode: 'stretch', + allowedBlocks: [ 'core/image' ], + orientation: 'horizontal', + renderAppender: false, + numColumns: displayedColumns, + marginHorizontal: TILE_SPACING, + marginVertical: TILE_SPACING, + __experimentalLayout: { type: 'default', alignments: [] }, + gridProperties: { + numColumns: displayedColumns, + }, + parentWidth: maxWidth + 2 * TILE_SPACING, + } + ); const focusGalleryCaption = () => { if ( ! isCaptionSelected ) { setIsCaptionSelected( true ); } - onFocusGalleryCaption(); }; + const isFullWidth = align === WIDE_ALIGNMENTS.alignments.full; + return ( - - + { resizeObserver } + + - { images.map( ( img, index ) => { - const ariaLabel = sprintf( - /* translators: 1: the order number of the image. 2: the total number of images. */ - __( 'image %1$d of %2$d in gallery' ), - index + 1, - images.length - ); - - return ( - - onSetImageAttributes( index, attrs ) - } - caption={ img.caption } - aria-label={ ariaLabel } - isRTL={ isRTL } - /> - ); - } ) } - - { mediaPlaceholder } { accessibilityLabelCreator={ ( caption ) => isEmpty( caption ) ? /* translators: accessibility text. Empty gallery caption. */ + 'Gallery caption. Empty' : sprintf( /* translators: accessibility text. %s: gallery caption. */ diff --git a/packages/block-library/src/gallery/gallery-button.native.js b/packages/block-library/src/gallery/v1/gallery-button.native.js similarity index 100% rename from packages/block-library/src/gallery/gallery-button.native.js rename to packages/block-library/src/gallery/v1/gallery-button.native.js diff --git a/packages/block-library/src/gallery/gallery-image-style.native.scss b/packages/block-library/src/gallery/v1/gallery-image-style.native.scss similarity index 100% rename from packages/block-library/src/gallery/gallery-image-style.native.scss rename to packages/block-library/src/gallery/v1/gallery-image-style.native.scss diff --git a/packages/block-library/src/gallery/gallery-image.native.js b/packages/block-library/src/gallery/v1/gallery-image.native.js similarity index 100% rename from packages/block-library/src/gallery/gallery-image.native.js rename to packages/block-library/src/gallery/v1/gallery-image.native.js diff --git a/packages/block-library/src/gallery/v1/gallery-styles.native.scss b/packages/block-library/src/gallery/v1/gallery-styles.native.scss new file mode 100644 index 00000000000000..9b3169da048b22 --- /dev/null +++ b/packages/block-library/src/gallery/v1/gallery-styles.native.scss @@ -0,0 +1,8 @@ +.galleryTilesContainerSelected { + margin-bottom: 16px; +} + +.fullWidth { + margin-left: $block-edge-to-content; + margin-right: $block-edge-to-content; +} diff --git a/packages/block-library/src/gallery/v1/gallery.native.js b/packages/block-library/src/gallery/v1/gallery.native.js new file mode 100644 index 00000000000000..4adb432b93f1e6 --- /dev/null +++ b/packages/block-library/src/gallery/v1/gallery.native.js @@ -0,0 +1,162 @@ +/** + * External dependencies + */ +import { View } from 'react-native'; +import { isEmpty } from 'lodash'; + +/** + * Internal dependencies + */ +import GalleryImage from './gallery-image'; +import { defaultColumnsNumberV1 } from '../deprecated'; +import styles from './gallery-styles.scss'; +import Tiles from './tiles'; + +/** + * WordPress dependencies + */ +import { __, sprintf } from '@wordpress/i18n'; +import { + BlockCaption, + store as blockEditorStore, +} from '@wordpress/block-editor'; +import { useState, useEffect } from '@wordpress/element'; +import { mediaUploadSync } from '@wordpress/react-native-bridge'; +import { useSelect } from '@wordpress/data'; +import { alignmentHelpers } from '@wordpress/components'; + +const TILE_SPACING = 15; + +// we must limit displayed columns since readable content max-width is 580px +const MAX_DISPLAYED_COLUMNS = 4; +const MAX_DISPLAYED_COLUMNS_NARROW = 2; + +const { isFullWidth } = alignmentHelpers; + +export const Gallery = ( props ) => { + const [ isCaptionSelected, setIsCaptionSelected ] = useState( false ); + useEffect( mediaUploadSync, [] ); + + const isRTL = useSelect( ( select ) => { + return !! select( blockEditorStore ).getSettings().isRTL; + }, [] ); + + const { + clientId, + selectedImage, + mediaPlaceholder, + onBlur, + onMoveBackward, + onMoveForward, + onRemoveImage, + onSelectImage, + onSetImageAttributes, + onFocusGalleryCaption, + attributes, + isSelected, + isNarrow, + onFocus, + insertBlocksAfter, + } = props; + + const { + align, + columns = defaultColumnsNumberV1( attributes ), + imageCrop, + images, + } = attributes; + + // limit displayed columns when isNarrow is true (i.e. when viewport width is + // less than "small", where small = 600) + const displayedColumns = isNarrow + ? Math.min( columns, MAX_DISPLAYED_COLUMNS_NARROW ) + : Math.min( columns, MAX_DISPLAYED_COLUMNS ); + + const selectImage = ( index ) => { + return () => { + if ( isCaptionSelected ) { + setIsCaptionSelected( false ); + } + // we need to fully invoke the curried function here + onSelectImage( index )(); + }; + }; + + const focusGalleryCaption = () => { + if ( ! isCaptionSelected ) { + setIsCaptionSelected( true ); + } + onFocusGalleryCaption(); + }; + + return ( + + + { images.map( ( img, index ) => { + const ariaLabel = sprintf( + /* translators: 1: the order number of the image. 2: the total number of images. */ + __( 'image %1$d of %2$d in gallery' ), + index + 1, + images.length + ); + + return ( + + onSetImageAttributes( index, attrs ) + } + caption={ img.caption } + aria-label={ ariaLabel } + isRTL={ isRTL } + /> + ); + } ) } + + + { mediaPlaceholder } + + + isEmpty( caption ) + ? /* translators: accessibility text. Empty gallery caption. */ + 'Gallery caption. Empty' + : sprintf( + /* translators: accessibility text. %s: gallery caption. */ + __( 'Gallery caption. %s' ), + caption + ) + } + onFocus={ focusGalleryCaption } + onBlur={ onBlur } // always assign onBlur as props + insertBlocksAfter={ insertBlocksAfter } + /> + + ); +}; + +export default Gallery; diff --git a/packages/block-library/src/gallery/tiles-styles.native.scss b/packages/block-library/src/gallery/v1/tiles-styles.native.scss similarity index 100% rename from packages/block-library/src/gallery/tiles-styles.native.scss rename to packages/block-library/src/gallery/v1/tiles-styles.native.scss diff --git a/packages/block-library/src/gallery/tiles.native.js b/packages/block-library/src/gallery/v1/tiles.native.js similarity index 100% rename from packages/block-library/src/gallery/tiles.native.js rename to packages/block-library/src/gallery/v1/tiles.native.js diff --git a/packages/block-library/src/image/edit.native.js b/packages/block-library/src/image/edit.native.js index 5ea885333ad69a..5c7740374fc88e 100644 --- a/packages/block-library/src/image/edit.native.js +++ b/packages/block-library/src/image/edit.native.js @@ -63,6 +63,8 @@ import { getUpdatedLinkTargetSettings } from './utils'; import { LINK_DESTINATION_CUSTOM, + LINK_DESTINATION_ATTACHMENT, + LINK_DESTINATION_MEDIA, MEDIA_ID_NO_FEATURED_IMAGE_SET, } from './constants'; @@ -171,12 +173,12 @@ export class ImageEdit extends Component { } componentDidUpdate( previousProps ) { - if ( ! previousProps.image && this.props.image ) { - const { image, attributes } = this.props; + const { image, attributes, setAttributes } = this.props; + if ( ! previousProps.image && image ) { const url = getUrlForSlug( image, attributes?.sizeSlug ) || image.source_url; - this.props.setAttributes( { url } ); + setAttributes( { url } ); } } @@ -292,14 +294,13 @@ export class ImageEdit extends Component { } onSetSizeSlug( sizeSlug ) { - const { image } = this.props; + const { image, setAttributes } = this.props; const url = getUrlForSlug( image, sizeSlug ); if ( ! url ) { return null; } - - this.props.setAttributes( { + setAttributes( { url, width: undefined, height: undefined, @@ -308,11 +309,8 @@ export class ImageEdit extends Component { } onSelectMediaUploadOption( media ) { - const { - attributes: { id, url }, - imageDefaultSize, - } = this.props; - + const { imageDefaultSize } = this.props; + const { id, url, destination } = this.props.attributes; const mediaAttributes = { id: media.id, url: media.url, @@ -332,6 +330,17 @@ export class ImageEdit extends Component { additionalAttributes = { url }; } + let href; + switch ( destination ) { + case LINK_DESTINATION_MEDIA: + href = media.url; + break; + case LINK_DESTINATION_ATTACHMENT: + href = media.link; + break; + } + mediaAttributes.href = href; + this.props.setAttributes( { ...mediaAttributes, ...additionalAttributes, @@ -372,9 +381,17 @@ export class ImageEdit extends Component { setMappedAttributes( { url: href, ...restAttributes } ) { const { setAttributes } = this.props; + return href === undefined - ? setAttributes( restAttributes ) - : setAttributes( { ...restAttributes, href } ); + ? setAttributes( { + ...restAttributes, + linkDestination: LINK_DESTINATION_CUSTOM, + } ) + : setAttributes( { + ...restAttributes, + href, + linkDestination: LINK_DESTINATION_CUSTOM, + } ); } getLinkSettings() { @@ -382,7 +399,6 @@ export class ImageEdit extends Component { const { attributes: { href: url, ...unMappedAttributes }, } = this.props; - const mappedAttributes = { ...unMappedAttributes, url }; return ( @@ -491,6 +507,7 @@ export class ImageEdit extends Component { image, clientId, imageDefaultSize, + context: { imageCrop = false } = {}, featuredImageId, wasBlockJustInserted, } = this.props; @@ -594,6 +611,11 @@ export class ImageEdit extends Component { wide: 'center', }; + const additionalImageProps = { + height: '100%', + resizeMode: imageCrop ? 'cover' : 'contain', + }; + const getImageComponent = ( openMediaOptions, getMediaOptions ) => ( { return ( - { + + { + ); } } /> diff --git a/packages/block-library/src/image/styles.native.scss b/packages/block-library/src/image/styles.native.scss index 66f4a02cb66217..3c192ca4b0d219 100644 --- a/packages/block-library/src/image/styles.native.scss +++ b/packages/block-library/src/image/styles.native.scss @@ -31,6 +31,11 @@ padding-bottom: $grid-unit; } +.isGallery { + height: 150; + overflow: visible; +} + .setFeaturedButton { border-top-width: $border-width; border-top-color: $light-gray-400; diff --git a/packages/element/src/platform.android.js b/packages/element/src/platform.android.js index 9f9bd4c0d9e4c9..e6be5eb051e0b2 100644 --- a/packages/element/src/platform.android.js +++ b/packages/element/src/platform.android.js @@ -14,6 +14,8 @@ const Platform = { } return spec.default; }, + isNative: true, + isAndroid: true, }; export default Platform; diff --git a/packages/element/src/platform.ios.js b/packages/element/src/platform.ios.js index f5833141e33028..c29a4006143d47 100644 --- a/packages/element/src/platform.ios.js +++ b/packages/element/src/platform.ios.js @@ -14,6 +14,8 @@ const Platform = { } return spec.default; }, + isNative: true, + isIOS: true, }; export default Platform; diff --git a/packages/element/src/platform.js b/packages/element/src/platform.js index 328f5523b6f95f..c646b6c86d51a2 100644 --- a/packages/element/src/platform.js +++ b/packages/element/src/platform.js @@ -9,6 +9,7 @@ const Platform = { OS: 'web', select: ( spec ) => ( 'web' in spec ? spec.web : spec.default ), + isWeb: true, }; /** * Component used to detect the current Platform being used.