@wordpress/block-library
Version:
Block library for the WordPress editor.
5 lines • 59 kB
Source Map (JSON)
{
"version": 3,
"sources": ["../../src/image/image.js"],
"sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { isBlobURL } from '@wordpress/blob';\nimport {\n\tExternalLink,\n\tFocalPointPicker,\n\tResizableBox,\n\tSpinner,\n\tTextareaControl,\n\tTextControl,\n\tToolbarButton,\n\tToolbarGroup,\n\t__experimentalToolsPanel as ToolsPanel,\n\t__experimentalToolsPanelItem as ToolsPanelItem,\n\t__experimentalUseCustomUnits as useCustomUnits,\n\tPlaceholder,\n\tMenuItem,\n\tToolbarItem,\n\tDropdownMenu,\n\tPopover,\n} from '@wordpress/components';\nimport {\n\tuseMergeRefs,\n\tuseResizeObserver,\n\tuseViewportMatch,\n} from '@wordpress/compose';\nimport { useSelect, useDispatch } from '@wordpress/data';\nimport {\n\tBlockControls,\n\tInspectorControls,\n\t__experimentalImageURLInputUI as ImageURLInputUI,\n\tMediaReplaceFlow,\n\tstore as blockEditorStore,\n\tuseSettings,\n\t__experimentalImageEditor as ImageEditor,\n\t__experimentalUseBorderProps as useBorderProps,\n\t__experimentalGetShadowClassesAndStyles as getShadowClassesAndStyles,\n\tprivateApis as blockEditorPrivateApis,\n\tBlockSettingsMenuControls,\n} from '@wordpress/block-editor';\nimport { useCallback, useEffect, useMemo, useState } from '@wordpress/element';\nimport { __, _x, sprintf, isRTL } from '@wordpress/i18n';\nimport { getFilename } from '@wordpress/url';\nimport { getBlockBindingsSource, switchToBlockType } from '@wordpress/blocks';\nimport { crop, overlayText, upload, chevronDown } from '@wordpress/icons';\nimport { store as noticesStore } from '@wordpress/notices';\nimport { store as coreStore } from '@wordpress/core-data';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../lock-unlock';\nimport { createUpgradedEmbedBlock } from '../embed/util';\nimport { isExternalImage } from './edit';\nimport { Caption } from '../utils/caption';\nimport { MediaControl } from '../utils/media-control';\nimport { useToolsPanelDropdownMenuProps } from '../utils/hooks';\nimport {\n\tMIN_SIZE,\n\tALLOWED_MEDIA_TYPES,\n\tSIZED_LAYOUTS,\n\tDEFAULT_MEDIA_SIZE_SLUG,\n} from './constants';\nimport { evalAspectRatio, mediaPosition } from './utils';\n\nconst { DimensionsTool, ResolutionTool } = unlock( blockEditorPrivateApis );\n\nconst scaleOptions = [\n\t{\n\t\tvalue: 'cover',\n\t\tlabel: _x( 'Cover', 'Scale option for dimensions control' ),\n\t\thelp: __( 'Image covers the space evenly.' ),\n\t},\n\t{\n\t\tvalue: 'contain',\n\t\tlabel: _x( 'Contain', 'Scale option for dimensions control' ),\n\t\thelp: __( 'Image is contained without distortion.' ),\n\t},\n];\n\nconst WRITEMODE_POPOVER_PROPS = {\n\tplacement: 'bottom-start',\n};\n\n// If the image has a href, wrap in an <a /> tag to trigger any inherited link element styles.\nconst ImageWrapper = ( { href, children } ) => {\n\tif ( ! href ) {\n\t\treturn children;\n\t}\n\treturn (\n\t\t<a\n\t\t\thref={ href }\n\t\t\tonClick={ ( event ) => event.preventDefault() }\n\t\t\taria-disabled\n\t\t\tstyle={ {\n\t\t\t\t// When the Image block is linked,\n\t\t\t\t// it's wrapped with a disabled <a /> tag.\n\t\t\t\t// Restore cursor style so it doesn't appear 'clickable'\n\t\t\t\t// and remove pointer events. Safari needs the display property.\n\t\t\t\tpointerEvents: 'none',\n\t\t\t\tcursor: 'default',\n\t\t\t\tdisplay: 'inline',\n\t\t\t} }\n\t\t>\n\t\t\t{ children }\n\t\t</a>\n\t);\n};\n\nfunction ContentOnlyControls( {\n\tattributes,\n\tsetAttributes,\n\tlockAltControls,\n\tlockAltControlsMessage,\n\tlockTitleControls,\n\tlockTitleControlsMessage,\n} ) {\n\t// Use internal state instead of a ref to make sure that the component\n\t// re-renders when the popover's anchor updates.\n\tconst [ popoverAnchor, setPopoverAnchor ] = useState( null );\n\tconst [ isAltDialogOpen, setIsAltDialogOpen ] = useState( false );\n\tconst [ isTitleDialogOpen, setIsTitleDialogOpen ] = useState( false );\n\treturn (\n\t\t<>\n\t\t\t<ToolbarItem ref={ setPopoverAnchor }>\n\t\t\t\t{ ( toggleProps ) => (\n\t\t\t\t\t<DropdownMenu\n\t\t\t\t\t\ticon={ chevronDown }\n\t\t\t\t\t\t/* translators: button label text should, if possible, be under 16 characters. */\n\t\t\t\t\t\tlabel={ __( 'More' ) }\n\t\t\t\t\t\ttoggleProps={ {\n\t\t\t\t\t\t\t...toggleProps,\n\t\t\t\t\t\t\tdescription: __( 'Displays more controls.' ),\n\t\t\t\t\t\t} }\n\t\t\t\t\t\tpopoverProps={ WRITEMODE_POPOVER_PROPS }\n\t\t\t\t\t>\n\t\t\t\t\t\t{ ( { onClose } ) => (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\tonClick={ () => {\n\t\t\t\t\t\t\t\t\t\tsetIsAltDialogOpen( true );\n\t\t\t\t\t\t\t\t\t\tonClose();\n\t\t\t\t\t\t\t\t\t} }\n\t\t\t\t\t\t\t\t\taria-haspopup=\"dialog\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{ _x(\n\t\t\t\t\t\t\t\t\t\t'Alternative text',\n\t\t\t\t\t\t\t\t\t\t'Alternative text for an image. Block toolbar label, a low character count is preferred.'\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t\t<MenuItem\n\t\t\t\t\t\t\t\t\tonClick={ () => {\n\t\t\t\t\t\t\t\t\t\tsetIsTitleDialogOpen( true );\n\t\t\t\t\t\t\t\t\t\tonClose();\n\t\t\t\t\t\t\t\t\t} }\n\t\t\t\t\t\t\t\t\taria-haspopup=\"dialog\"\n\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t{ __( 'Title text' ) }\n\t\t\t\t\t\t\t\t</MenuItem>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t) }\n\t\t\t\t\t</DropdownMenu>\n\t\t\t\t) }\n\t\t\t</ToolbarItem>\n\t\t\t{ isAltDialogOpen && (\n\t\t\t\t<Popover\n\t\t\t\t\tplacement=\"bottom-start\"\n\t\t\t\t\tanchor={ popoverAnchor }\n\t\t\t\t\tonClose={ () => setIsAltDialogOpen( false ) }\n\t\t\t\t\toffset={ 13 }\n\t\t\t\t\tvariant=\"toolbar\"\n\t\t\t\t>\n\t\t\t\t\t<div className=\"wp-block-image__toolbar_content_textarea__container\">\n\t\t\t\t\t\t<TextareaControl\n\t\t\t\t\t\t\tclassName=\"wp-block-image__toolbar_content_textarea\"\n\t\t\t\t\t\t\tlabel={ __( 'Alternative text' ) }\n\t\t\t\t\t\t\tvalue={ attributes.alt || '' }\n\t\t\t\t\t\t\tonChange={ ( value ) =>\n\t\t\t\t\t\t\t\tsetAttributes( { alt: value } )\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdisabled={ lockAltControls }\n\t\t\t\t\t\t\thelp={\n\t\t\t\t\t\t\t\tlockAltControls ? (\n\t\t\t\t\t\t\t\t\t<>{ lockAltControlsMessage }</>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t<ExternalLink\n\t\t\t\t\t\t\t\t\t\t\thref={\n\t\t\t\t\t\t\t\t\t\t\t\t// translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations.\n\t\t\t\t\t\t\t\t\t\t\t\t__(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'https://www.w3.org/WAI/tutorials/images/decision-tree/'\n\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t{ __(\n\t\t\t\t\t\t\t\t\t\t\t\t'Describe the purpose of the image.'\n\t\t\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\t\t</ExternalLink>\n\t\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t\t\t{ __( 'Leave empty if decorative.' ) }\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</Popover>\n\t\t\t) }\n\t\t\t{ isTitleDialogOpen && (\n\t\t\t\t<Popover\n\t\t\t\t\tplacement=\"bottom-start\"\n\t\t\t\t\tanchor={ popoverAnchor }\n\t\t\t\t\tonClose={ () => setIsTitleDialogOpen( false ) }\n\t\t\t\t\toffset={ 13 }\n\t\t\t\t\tvariant=\"toolbar\"\n\t\t\t\t>\n\t\t\t\t\t<div className=\"wp-block-image__toolbar_content_textarea__container\">\n\t\t\t\t\t\t<TextControl\n\t\t\t\t\t\t\t__next40pxDefaultSize\n\t\t\t\t\t\t\tclassName=\"wp-block-image__toolbar_content_textarea\"\n\t\t\t\t\t\t\tlabel={ __( 'Title attribute' ) }\n\t\t\t\t\t\t\tvalue={ attributes.title || '' }\n\t\t\t\t\t\t\tonChange={ ( value ) =>\n\t\t\t\t\t\t\t\tsetAttributes( {\n\t\t\t\t\t\t\t\t\ttitle: value,\n\t\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tdisabled={ lockTitleControls }\n\t\t\t\t\t\t\thelp={\n\t\t\t\t\t\t\t\tlockTitleControls ? (\n\t\t\t\t\t\t\t\t\t<>{ lockTitleControlsMessage }</>\n\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t{ __(\n\t\t\t\t\t\t\t\t\t\t\t'Describe the role of this image on the page.'\n\t\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\t\t<ExternalLink href=\"https://www.w3.org/TR/html52/dom.html#the-title-attribute\">\n\t\t\t\t\t\t\t\t\t\t\t{ __(\n\t\t\t\t\t\t\t\t\t\t\t\t'(Note: many devices and browsers do not display this text.)'\n\t\t\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\t\t</ExternalLink>\n\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</div>\n\t\t\t\t</Popover>\n\t\t\t) }\n\t\t</>\n\t);\n}\n\nexport default function Image( {\n\ttemporaryURL,\n\tattributes,\n\tsetAttributes,\n\tisSingleSelected,\n\tinsertBlocksAfter,\n\tonReplace,\n\tonSelectImage,\n\tonSelectURL,\n\tonUploadError,\n\tcontext,\n\tclientId,\n\tblockEditingMode,\n\tparentLayoutType,\n\tmaxContentWidth,\n} ) {\n\tconst {\n\t\turl = '',\n\t\talt,\n\t\talign,\n\t\tid,\n\t\thref,\n\t\trel,\n\t\tlinkClass,\n\t\tlinkDestination,\n\t\ttitle,\n\t\twidth,\n\t\theight,\n\t\taspectRatio,\n\t\tscale,\n\t\tfocalPoint,\n\t\tlinkTarget,\n\t\tsizeSlug,\n\t\tlightbox,\n\t\tmetadata,\n\t} = attributes;\n\tconst [ imageElement, setImageElement ] = useState();\n\tconst [ resizeDelta, setResizeDelta ] = useState( null );\n\tconst [ pixelSize, setPixelSize ] = useState( {} );\n\tconst [ offsetTop, setOffsetTop ] = useState( 0 );\n\tconst setResizeObserved = useResizeObserver( ( [ entry ] ) => {\n\t\tif ( ! resizeDelta ) {\n\t\t\tconst [ box ] = entry.borderBoxSize;\n\t\t\tsetPixelSize( { width: box.inlineSize, height: box.blockSize } );\n\t\t}\n\t\t// This is usually 0 unless the image height is less than the line-height.\n\t\tsetOffsetTop( entry.target.offsetTop );\n\t} );\n\tconst effectResizeableBoxPlacement = useCallback( () => {\n\t\tsetOffsetTop( imageElement?.offsetTop ?? 0 );\n\t}, [ imageElement ] );\n\tconst setRefs = useMergeRefs( [ setImageElement, setResizeObserved ] );\n\tconst { allowResize = true } = context;\n\n\tconst { image, canUserEdit } = useSelect(\n\t\t( select ) => {\n\t\t\tconst imageRecord =\n\t\t\t\tid && isSingleSelected\n\t\t\t\t\t? select( coreStore ).getEntityRecord(\n\t\t\t\t\t\t\t'postType',\n\t\t\t\t\t\t\t'attachment',\n\t\t\t\t\t\t\tid,\n\t\t\t\t\t\t\t{ context: 'view' }\n\t\t\t\t\t )\n\t\t\t\t\t: null;\n\n\t\t\t// Check edit permissions. When the media editor experiment is enabled,\n\t\t\t// use getEntityRecordPermissions which checks via canUser API.\n\t\t\t// Only check when the image is selected to avoid unnecessary API requests.\n\t\t\tlet canEdit = false;\n\t\t\tif ( id && isSingleSelected && window?.__experimentalMediaEditor ) {\n\t\t\t\tconst { getEntityRecordPermissions } = unlock(\n\t\t\t\t\tselect( coreStore )\n\t\t\t\t);\n\t\t\t\tconst permissions = getEntityRecordPermissions(\n\t\t\t\t\t'postType',\n\t\t\t\t\t'attachment',\n\t\t\t\t\tid\n\t\t\t\t);\n\t\t\t\tcanEdit = permissions?.update || false;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\timage: imageRecord,\n\t\t\t\tcanUserEdit: canEdit,\n\t\t\t};\n\t\t},\n\t\t[ id, isSingleSelected ]\n\t);\n\n\tconst { canInsertCover, imageEditing, imageSizes, maxWidth } = useSelect(\n\t\t( select ) => {\n\t\t\tconst { getBlockRootClientId, canInsertBlockType, getSettings } =\n\t\t\t\tselect( blockEditorStore );\n\n\t\t\tconst rootClientId = getBlockRootClientId( clientId );\n\t\t\tconst settings = getSettings();\n\n\t\t\treturn {\n\t\t\t\timageEditing: settings.imageEditing,\n\t\t\t\timageSizes: settings.imageSizes,\n\t\t\t\tmaxWidth: settings.maxWidth,\n\t\t\t\tcanInsertCover: canInsertBlockType(\n\t\t\t\t\t'core/cover',\n\t\t\t\t\trootClientId\n\t\t\t\t),\n\t\t\t};\n\t\t},\n\t\t[ clientId ]\n\t);\n\tconst { getBlock, getSettings } = useSelect( blockEditorStore );\n\tconst onNavigateToEntityRecord = getSettings().onNavigateToEntityRecord;\n\n\tconst { replaceBlocks, toggleSelection } = useDispatch( blockEditorStore );\n\tconst { createErrorNotice, createSuccessNotice } =\n\t\tuseDispatch( noticesStore );\n\tconst { editEntityRecord } = useDispatch( coreStore );\n\n\tconst isLargeViewport = useViewportMatch( 'medium' );\n\tconst isWideAligned = [ 'wide', 'full' ].includes( align );\n\tconst [\n\t\t{ loadedNaturalWidth, loadedNaturalHeight },\n\t\tsetLoadedNaturalSize,\n\t] = useState( {} );\n\tconst [ isEditingImage, setIsEditingImage ] = useState( false );\n\tconst [ externalBlob, setExternalBlob ] = useState();\n\tconst [ hasImageErrored, setHasImageErrored ] = useState( false );\n\tconst hasNonContentControls = blockEditingMode === 'default';\n\tconst isContentOnlyMode = blockEditingMode === 'contentOnly';\n\tconst showDimensionsControls = allowResize && hasNonContentControls;\n\tconst isResizable =\n\t\tallowResize &&\n\t\thasNonContentControls &&\n\t\t! isWideAligned &&\n\t\tisLargeViewport;\n\tconst imageSizeOptions = imageSizes\n\t\t.filter(\n\t\t\t( { slug } ) => image?.media_details?.sizes?.[ slug ]?.source_url\n\t\t)\n\t\t.map( ( { name, slug } ) => ( { value: slug, label: name } ) );\n\n\t// If an image is externally hosted, try to fetch the image data. This may\n\t// fail if the image host doesn't allow CORS with the domain. If it works,\n\t// we can enable a button in the toolbar to upload the image.\n\tuseEffect( () => {\n\t\tif (\n\t\t\t! isExternalImage( id, url ) ||\n\t\t\t! isSingleSelected ||\n\t\t\t! getSettings().mediaUpload\n\t\t) {\n\t\t\tsetExternalBlob();\n\t\t\treturn;\n\t\t}\n\n\t\tif ( externalBlob ) {\n\t\t\treturn;\n\t\t}\n\n\t\twindow\n\t\t\t// Avoid cache, which seems to help avoid CORS problems.\n\t\t\t.fetch( url.includes( '?' ) ? url : url + '?' )\n\t\t\t.then( ( response ) => response.blob() )\n\t\t\t.then( ( blob ) => setExternalBlob( blob ) )\n\t\t\t// Do nothing, cannot upload.\n\t\t\t.catch( () => {} );\n\t}, [ id, url, isSingleSelected, externalBlob, getSettings ] );\n\n\t// Get naturalWidth and naturalHeight from image, and fall back to loaded natural\n\t// width and height. This resolves an issue in Safari where the loaded natural\n\t// width and height is otherwise lost when switching between alignments.\n\t// See: https://github.com/WordPress/gutenberg/pull/37210.\n\tconst { naturalWidth, naturalHeight } = useMemo( () => {\n\t\treturn {\n\t\t\tnaturalWidth:\n\t\t\t\timageElement?.naturalWidth || loadedNaturalWidth || undefined,\n\t\t\tnaturalHeight:\n\t\t\t\timageElement?.naturalHeight || loadedNaturalHeight || undefined,\n\t\t};\n\t}, [ loadedNaturalWidth, loadedNaturalHeight, imageElement?.complete ] );\n\n\tfunction onImageError() {\n\t\tsetHasImageErrored( true );\n\n\t\t// Check if there's an embed block that handles this URL, e.g., instagram URL.\n\t\t// See: https://github.com/WordPress/gutenberg/pull/11472\n\t\tconst embedBlock = createUpgradedEmbedBlock( { attributes: { url } } );\n\t\tif ( undefined !== embedBlock ) {\n\t\t\tonReplace( embedBlock );\n\t\t}\n\t}\n\n\tfunction onImageLoad( event ) {\n\t\tsetHasImageErrored( false );\n\t\tsetLoadedNaturalSize( {\n\t\t\tloadedNaturalWidth: event.target?.naturalWidth,\n\t\t\tloadedNaturalHeight: event.target?.naturalHeight,\n\t\t} );\n\t}\n\n\tfunction onSetHref( props ) {\n\t\tsetAttributes( props );\n\t}\n\n\tfunction onSetLightbox( enable ) {\n\t\tif ( enable && ! lightboxSetting?.enabled ) {\n\t\t\tsetAttributes( {\n\t\t\t\tlightbox: { enabled: true },\n\t\t\t} );\n\t\t} else if ( ! enable && lightboxSetting?.enabled ) {\n\t\t\tsetAttributes( {\n\t\t\t\tlightbox: { enabled: false },\n\t\t\t} );\n\t\t} else {\n\t\t\tsetAttributes( {\n\t\t\t\tlightbox: undefined,\n\t\t\t} );\n\t\t}\n\t}\n\n\tfunction resetLightbox() {\n\t\t// When deleting a link from an image while lightbox settings\n\t\t// are enabled by default, we should disable the lightbox,\n\t\t// otherwise the resulting UX looks like a mistake.\n\t\t// See https://github.com/WordPress/gutenberg/pull/59890/files#r1532286123.\n\t\tif ( lightboxSetting?.enabled && lightboxSetting?.allowEditing ) {\n\t\t\tsetAttributes( {\n\t\t\t\tlightbox: { enabled: false },\n\t\t\t} );\n\t\t} else {\n\t\t\tsetAttributes( {\n\t\t\t\tlightbox: undefined,\n\t\t\t} );\n\t\t}\n\t}\n\n\tfunction onSetTitle( value ) {\n\t\t// This is the HTML title attribute, separate from the media object\n\t\t// title.\n\t\tsetAttributes( { title: value } );\n\t}\n\n\tfunction updateAlt( newAlt ) {\n\t\tsetAttributes( { alt: newAlt } );\n\t}\n\n\tconst imperativeFocalPointPreview = ( value ) => {\n\t\tif ( imageElement ) {\n\t\t\timageElement.style.setProperty(\n\t\t\t\t'object-position',\n\t\t\t\tmediaPosition( value )\n\t\t\t);\n\t\t}\n\t};\n\n\tfunction updateImage( newSizeSlug ) {\n\t\tconst newUrl = image?.media_details?.sizes?.[ newSizeSlug ]?.source_url;\n\t\tif ( ! newUrl ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tsetAttributes( {\n\t\t\turl: newUrl,\n\t\t\tsizeSlug: newSizeSlug,\n\t\t} );\n\t}\n\n\tfunction uploadExternal() {\n\t\tconst { mediaUpload } = getSettings();\n\t\tif ( ! mediaUpload ) {\n\t\t\treturn;\n\t\t}\n\t\tmediaUpload( {\n\t\t\tfilesList: [ externalBlob ],\n\t\t\tonFileChange( [ img ] ) {\n\t\t\t\tonSelectImage( img );\n\n\t\t\t\tif ( isBlobURL( img.url ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tsetExternalBlob();\n\t\t\t\tcreateSuccessNotice( __( 'Image uploaded.' ), {\n\t\t\t\t\ttype: 'snackbar',\n\t\t\t\t} );\n\t\t\t},\n\t\t\tallowedTypes: ALLOWED_MEDIA_TYPES,\n\t\t\tonError( message ) {\n\t\t\t\tcreateErrorNotice( message, { type: 'snackbar' } );\n\t\t\t},\n\t\t} );\n\t}\n\n\tuseEffect( () => {\n\t\tif ( ! isSingleSelected ) {\n\t\t\tsetIsEditingImage( false );\n\t\t}\n\t}, [ isSingleSelected ] );\n\n\tconst canEditImage = id && naturalWidth && naturalHeight && imageEditing;\n\tconst allowCrop =\n\t\tisSingleSelected &&\n\t\tcanEditImage &&\n\t\t! isEditingImage &&\n\t\t! isContentOnlyMode;\n\n\tfunction switchToCover() {\n\t\treplaceBlocks(\n\t\t\tclientId,\n\t\t\tswitchToBlockType( getBlock( clientId ), 'core/cover' )\n\t\t);\n\t}\n\n\t// TODO: Can allow more units after figuring out how they should interact\n\t// with the ResizableBox and ImageEditor components. Calculations later on\n\t// for those components are currently assuming px units.\n\tconst dimensionsUnitsOptions = useCustomUnits( {\n\t\tavailableUnits: [ 'px' ],\n\t} );\n\n\tconst [ lightboxSetting ] = useSettings( 'lightbox' );\n\n\tconst showLightboxSetting =\n\t\t// If a block-level override is set, we should give users the option to\n\t\t// remove that override, even if the lightbox UI is disabled in the settings.\n\t\t( !! lightbox && lightbox?.enabled !== lightboxSetting?.enabled ) ||\n\t\tlightboxSetting?.allowEditing;\n\n\tconst lightboxChecked =\n\t\t!! lightbox?.enabled || ( ! lightbox && !! lightboxSetting?.enabled );\n\n\tconst dropdownMenuProps = useToolsPanelDropdownMenuProps();\n\n\tconst dimensionsControl =\n\t\tshowDimensionsControls &&\n\t\t( SIZED_LAYOUTS.includes( parentLayoutType ) ? (\n\t\t\t<DimensionsTool\n\t\t\t\tpanelId={ clientId }\n\t\t\t\tvalue={ { aspectRatio } }\n\t\t\t\tonChange={ ( { aspectRatio: newAspectRatio } ) => {\n\t\t\t\t\tsetAttributes( {\n\t\t\t\t\t\taspectRatio: newAspectRatio,\n\t\t\t\t\t\tscale: 'cover',\n\t\t\t\t\t} );\n\t\t\t\t} }\n\t\t\t\tdefaultAspectRatio=\"auto\"\n\t\t\t\ttools={ [ 'aspectRatio' ] }\n\t\t\t/>\n\t\t) : (\n\t\t\t<DimensionsTool\n\t\t\t\tpanelId={ clientId }\n\t\t\t\tvalue={ { width, height, scale, aspectRatio } }\n\t\t\t\tonChange={ ( {\n\t\t\t\t\twidth: newWidth,\n\t\t\t\t\theight: newHeight,\n\t\t\t\t\tscale: newScale,\n\t\t\t\t\taspectRatio: newAspectRatio,\n\t\t\t\t} ) => {\n\t\t\t\t\t// Rebuilding the object forces setting `undefined`\n\t\t\t\t\t// for values that are removed since setAttributes\n\t\t\t\t\t// doesn't do anything with keys that aren't set.\n\t\t\t\t\tsetAttributes( {\n\t\t\t\t\t\t// CSS includes `height: auto`, but we need\n\t\t\t\t\t\t// `width: auto` to fix the aspect ratio when\n\t\t\t\t\t\t// only height is set due to the width and\n\t\t\t\t\t\t// height attributes set via the server.\n\t\t\t\t\t\twidth: ! newWidth && newHeight ? 'auto' : newWidth,\n\t\t\t\t\t\theight: newHeight,\n\t\t\t\t\t\tscale: newScale,\n\t\t\t\t\t\taspectRatio: newAspectRatio,\n\t\t\t\t\t} );\n\t\t\t\t} }\n\t\t\t\tdefaultScale=\"cover\"\n\t\t\t\tdefaultAspectRatio=\"auto\"\n\t\t\t\tscaleOptions={ scaleOptions }\n\t\t\t\tunitsOptions={ dimensionsUnitsOptions }\n\t\t\t\ttools={\n\t\t\t\t\tisWideAligned\n\t\t\t\t\t\t? [ 'aspectRatio', 'scale' ]\n\t\t\t\t\t\t: [ 'aspectRatio', 'widthHeight', 'scale' ]\n\t\t\t\t}\n\t\t\t/>\n\t\t) );\n\n\tconst resetSettings = () => {\n\t\tsetAttributes( {\n\t\t\tlightbox: undefined,\n\t\t} );\n\t\tupdateImage( DEFAULT_MEDIA_SIZE_SLUG );\n\t};\n\n\tconst arePatternOverridesEnabled =\n\t\tmetadata?.bindings?.__default?.source === 'core/pattern-overrides';\n\n\tconst {\n\t\tlockUrlControls = false,\n\t\tlockHrefControls = false,\n\t\tlockAltControls = false,\n\t\tlockAltControlsMessage,\n\t\tlockTitleControls = false,\n\t\tlockTitleControlsMessage,\n\t\thideCaptionControls = false,\n\t} = useSelect(\n\t\t( select ) => {\n\t\t\tif ( ! isSingleSelected ) {\n\t\t\t\treturn {};\n\t\t\t}\n\t\t\tconst {\n\t\t\t\turl: urlBinding,\n\t\t\t\talt: altBinding,\n\t\t\t\ttitle: titleBinding,\n\t\t\t\tcaption: captionBinding,\n\t\t\t} = metadata?.bindings || {};\n\t\t\tconst hasParentPattern = !! context[ 'pattern/overrides' ];\n\t\t\tconst urlBindingSource = getBlockBindingsSource(\n\t\t\t\turlBinding?.source\n\t\t\t);\n\t\t\tconst altBindingSource = getBlockBindingsSource(\n\t\t\t\taltBinding?.source\n\t\t\t);\n\t\t\tconst titleBindingSource = getBlockBindingsSource(\n\t\t\t\ttitleBinding?.source\n\t\t\t);\n\t\t\treturn {\n\t\t\t\tlockUrlControls:\n\t\t\t\t\t!! urlBinding &&\n\t\t\t\t\t! urlBindingSource?.canUserEditValue?.( {\n\t\t\t\t\t\tselect,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\targs: urlBinding?.args,\n\t\t\t\t\t} ),\n\t\t\t\tlockHrefControls:\n\t\t\t\t\t// Disable editing the link of the URL if the image is inside a pattern instance.\n\t\t\t\t\t// This is a temporary solution until we support overriding the link on the frontend.\n\t\t\t\t\thasParentPattern || arePatternOverridesEnabled,\n\t\t\t\thideCaptionControls: !! captionBinding,\n\t\t\t\tlockAltControls:\n\t\t\t\t\t!! altBinding &&\n\t\t\t\t\t! altBindingSource?.canUserEditValue?.( {\n\t\t\t\t\t\tselect,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\targs: altBinding?.args,\n\t\t\t\t\t} ),\n\t\t\t\tlockAltControlsMessage: altBindingSource?.label\n\t\t\t\t\t? sprintf(\n\t\t\t\t\t\t\t/* translators: %s: Label of the bindings source. */\n\t\t\t\t\t\t\t__( 'Connected to %s' ),\n\t\t\t\t\t\t\taltBindingSource.label\n\t\t\t\t\t )\n\t\t\t\t\t: __( 'Connected to dynamic data' ),\n\t\t\t\tlockTitleControls:\n\t\t\t\t\t!! titleBinding &&\n\t\t\t\t\t! titleBindingSource?.canUserEditValue?.( {\n\t\t\t\t\t\tselect,\n\t\t\t\t\t\tcontext,\n\t\t\t\t\t\targs: titleBinding?.args,\n\t\t\t\t\t} ),\n\t\t\t\tlockTitleControlsMessage: titleBindingSource?.label\n\t\t\t\t\t? sprintf(\n\t\t\t\t\t\t\t/* translators: %s: Label of the bindings source. */\n\t\t\t\t\t\t\t__( 'Connected to %s' ),\n\t\t\t\t\t\t\ttitleBindingSource.label\n\t\t\t\t\t )\n\t\t\t\t\t: __( 'Connected to dynamic data' ),\n\t\t\t};\n\t\t},\n\t\t[\n\t\t\tarePatternOverridesEnabled,\n\t\t\tcontext,\n\t\t\tisSingleSelected,\n\t\t\tmetadata?.bindings,\n\t\t]\n\t);\n\n\tconst showUrlInput =\n\t\tisSingleSelected &&\n\t\t! isEditingImage &&\n\t\t! lockHrefControls &&\n\t\t! lockUrlControls;\n\n\tconst showCoverControls =\n\t\tisSingleSelected && canInsertCover && ! isContentOnlyMode;\n\n\tconst showBlockControls = showUrlInput || allowCrop || showCoverControls;\n\n\tconst mediaReplaceFlow = isSingleSelected &&\n\t\t! isEditingImage &&\n\t\t! lockUrlControls && (\n\t\t\t// For contentOnly mode, put this button in its own area so it has borders around it.\n\t\t\t<BlockControls group={ isContentOnlyMode ? 'inline' : 'other' }>\n\t\t\t\t<MediaReplaceFlow\n\t\t\t\t\tmediaId={ id }\n\t\t\t\t\tmediaURL={ url }\n\t\t\t\t\tallowedTypes={ ALLOWED_MEDIA_TYPES }\n\t\t\t\t\tonSelect={ onSelectImage }\n\t\t\t\t\tonSelectURL={ onSelectURL }\n\t\t\t\t\tonError={ onUploadError }\n\t\t\t\t\tname={ ! url ? __( 'Add image' ) : __( 'Replace' ) }\n\t\t\t\t\tonReset={ () => onSelectImage( undefined ) }\n\t\t\t\t\tvariant=\"toolbar\"\n\t\t\t\t/>\n\t\t\t</BlockControls>\n\t\t);\n\n\tconst hasDataFormBlockFields =\n\t\twindow?.__experimentalContentOnlyInspectorFields;\n\n\tconst editMediaButton = window?.__experimentalMediaEditor &&\n\t\tid &&\n\t\tisSingleSelected &&\n\t\tcanUserEdit &&\n\t\t! isExternalImage( id, url ) &&\n\t\t! isEditingImage &&\n\t\tonNavigateToEntityRecord && (\n\t\t\t<BlockControls group=\"other\">\n\t\t\t\t<ToolbarButton\n\t\t\t\t\tonClick={ () => {\n\t\t\t\t\t\tonNavigateToEntityRecord( {\n\t\t\t\t\t\t\tpostId: id,\n\t\t\t\t\t\t\tpostType: 'attachment',\n\t\t\t\t\t\t} );\n\t\t\t\t\t} }\n\t\t\t\t>\n\t\t\t\t\t{ __( 'Edit media' ) }\n\t\t\t\t</ToolbarButton>\n\t\t\t</BlockControls>\n\t\t);\n\n\tconst controls = (\n\t\t<>\n\t\t\t{ showBlockControls && (\n\t\t\t\t<BlockControls group=\"block\">\n\t\t\t\t\t{ showUrlInput && (\n\t\t\t\t\t\t<ImageURLInputUI\n\t\t\t\t\t\t\turl={ href || '' }\n\t\t\t\t\t\t\tonChangeUrl={ onSetHref }\n\t\t\t\t\t\t\tlinkDestination={ linkDestination }\n\t\t\t\t\t\t\tmediaUrl={ ( image && image.source_url ) || url }\n\t\t\t\t\t\t\tmediaLink={ image && image.link }\n\t\t\t\t\t\t\tlinkTarget={ linkTarget }\n\t\t\t\t\t\t\tlinkClass={ linkClass }\n\t\t\t\t\t\t\trel={ rel }\n\t\t\t\t\t\t\tshowLightboxSetting={ showLightboxSetting }\n\t\t\t\t\t\t\tlightboxEnabled={ lightboxChecked }\n\t\t\t\t\t\t\tonSetLightbox={ onSetLightbox }\n\t\t\t\t\t\t\tresetLightbox={ resetLightbox }\n\t\t\t\t\t\t/>\n\t\t\t\t\t) }\n\t\t\t\t\t{ allowCrop && (\n\t\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\t\tonClick={ () => setIsEditingImage( true ) }\n\t\t\t\t\t\t\ticon={ crop }\n\t\t\t\t\t\t\tlabel={ __( 'Crop' ) }\n\t\t\t\t\t\t/>\n\t\t\t\t\t) }\n\t\t\t\t\t{ showCoverControls && (\n\t\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\t\ticon={ overlayText }\n\t\t\t\t\t\t\tlabel={ __( 'Add text over image' ) }\n\t\t\t\t\t\t\tonClick={ switchToCover }\n\t\t\t\t\t\t/>\n\t\t\t\t\t) }\n\t\t\t\t</BlockControls>\n\t\t\t) }\n\t\t\t{ isSingleSelected && externalBlob && (\n\t\t\t\t<BlockControls>\n\t\t\t\t\t<ToolbarGroup>\n\t\t\t\t\t\t<ToolbarButton\n\t\t\t\t\t\t\tonClick={ uploadExternal }\n\t\t\t\t\t\t\ticon={ upload }\n\t\t\t\t\t\t\tlabel={ __( 'Upload to Media Library' ) }\n\t\t\t\t\t\t/>\n\t\t\t\t\t</ToolbarGroup>\n\t\t\t\t</BlockControls>\n\t\t\t) }\n\t\t\t{ isContentOnlyMode && (\n\t\t\t\t// Add some extra controls for content attributes when content only mode is active.\n\t\t\t\t// With content only mode active, the inspector is hidden, so users need another way\n\t\t\t\t// to edit these attributes.\n\t\t\t\t<BlockControls group=\"block\">\n\t\t\t\t\t<ContentOnlyControls\n\t\t\t\t\t\tattributes={ attributes }\n\t\t\t\t\t\tsetAttributes={ setAttributes }\n\t\t\t\t\t\tlockAltControls={ lockAltControls }\n\t\t\t\t\t\tlockAltControlsMessage={ lockAltControlsMessage }\n\t\t\t\t\t\tlockTitleControls={ lockTitleControls }\n\t\t\t\t\t\tlockTitleControlsMessage={ lockTitleControlsMessage }\n\t\t\t\t\t/>\n\t\t\t\t</BlockControls>\n\t\t\t) }\n\t\t\t{ ! hasDataFormBlockFields && isSingleSelected && (\n\t\t\t\t<InspectorControls group=\"content\">\n\t\t\t\t\t<ToolsPanel\n\t\t\t\t\t\tlabel={ __( 'Media' ) }\n\t\t\t\t\t\tresetAll={ () => onSelectImage( undefined ) }\n\t\t\t\t\t\tdropdownMenuProps={ dropdownMenuProps }\n\t\t\t\t\t>\n\t\t\t\t\t\t{ ! lockUrlControls && (\n\t\t\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\t\t\tlabel={ __( 'Image' ) }\n\t\t\t\t\t\t\t\thasValue={ () => !! url }\n\t\t\t\t\t\t\t\tonDeselect={ () => onSelectImage( undefined ) }\n\t\t\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t<MediaControl\n\t\t\t\t\t\t\t\t\tmediaId={ id }\n\t\t\t\t\t\t\t\t\tmediaUrl={ url }\n\t\t\t\t\t\t\t\t\talt={ alt }\n\t\t\t\t\t\t\t\t\tfilename={\n\t\t\t\t\t\t\t\t\t\timage?.media_details?.sizes?.full\n\t\t\t\t\t\t\t\t\t\t\t?.file ||\n\t\t\t\t\t\t\t\t\t\timage?.slug ||\n\t\t\t\t\t\t\t\t\t\tgetFilename( url )\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\tallowedTypes={ ALLOWED_MEDIA_TYPES }\n\t\t\t\t\t\t\t\t\tonSelect={ onSelectImage }\n\t\t\t\t\t\t\t\t\tonSelectURL={ onSelectURL }\n\t\t\t\t\t\t\t\t\tonError={ onUploadError }\n\t\t\t\t\t\t\t\t\tonReset={ () => onSelectImage( undefined ) }\n\t\t\t\t\t\t\t\t\tisUploading={ !! temporaryURL }\n\t\t\t\t\t\t\t\t\temptyLabel={ __( 'Add image' ) }\n\t\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t\t\t) }\n\t\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\t\tlabel={ __( 'Alternative text' ) }\n\t\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\t\thasValue={ () => !! alt }\n\t\t\t\t\t\t\tonDeselect={ () =>\n\t\t\t\t\t\t\t\tsetAttributes( { alt: undefined } )\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t>\n\t\t\t\t\t\t\t<TextareaControl\n\t\t\t\t\t\t\t\tlabel={ __( 'Alternative text' ) }\n\t\t\t\t\t\t\t\tvalue={ alt || '' }\n\t\t\t\t\t\t\t\tonChange={ updateAlt }\n\t\t\t\t\t\t\t\treadOnly={ lockAltControls }\n\t\t\t\t\t\t\t\thelp={\n\t\t\t\t\t\t\t\t\tlockAltControls ? (\n\t\t\t\t\t\t\t\t\t\t<>{ lockAltControlsMessage }</>\n\t\t\t\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t\t\t\t<ExternalLink\n\t\t\t\t\t\t\t\t\t\t\t\thref={\n\t\t\t\t\t\t\t\t\t\t\t\t\t// translators: Localized tutorial, if one exists. W3C Web Accessibility Initiative link has list of existing translations.\n\t\t\t\t\t\t\t\t\t\t\t\t\t__(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t'https://www.w3.org/WAI/tutorials/images/decision-tree/'\n\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t>\n\t\t\t\t\t\t\t\t\t\t\t\t{ __(\n\t\t\t\t\t\t\t\t\t\t\t\t\t'Describe the purpose of the image.'\n\t\t\t\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\t\t\t</ExternalLink>\n\t\t\t\t\t\t\t\t\t\t\t<br />\n\t\t\t\t\t\t\t\t\t\t\t{ __(\n\t\t\t\t\t\t\t\t\t\t\t\t'Leave empty if decorative.'\n\t\t\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t/>\n\t\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t\t</ToolsPanel>\n\t\t\t\t</InspectorControls>\n\t\t\t) }\n\t\t\t<InspectorControls\n\t\t\t\tgroup=\"dimensions\"\n\t\t\t\tresetAllFilter={ ( attrs ) => ( {\n\t\t\t\t\t...attrs,\n\t\t\t\t\taspectRatio: undefined,\n\t\t\t\t\twidth: undefined,\n\t\t\t\t\theight: undefined,\n\t\t\t\t\tscale: undefined,\n\t\t\t\t\tfocalPoint: undefined,\n\t\t\t\t} ) }\n\t\t\t>\n\t\t\t\t{ dimensionsControl }\n\t\t\t\t{ url && scale && (\n\t\t\t\t\t<ToolsPanelItem\n\t\t\t\t\t\tlabel={ __( 'Focal point' ) }\n\t\t\t\t\t\tisShownByDefault\n\t\t\t\t\t\thasValue={ () => !! focalPoint }\n\t\t\t\t\t\tonDeselect={ () =>\n\t\t\t\t\t\t\tsetAttributes( {\n\t\t\t\t\t\t\t\tfocalPoint: undefined,\n\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t}\n\t\t\t\t\t\tpanelId={ clientId }\n\t\t\t\t\t>\n\t\t\t\t\t\t<FocalPointPicker\n\t\t\t\t\t\t\tlabel={ __( 'Focal point' ) }\n\t\t\t\t\t\t\turl={ url }\n\t\t\t\t\t\t\tvalue={ focalPoint }\n\t\t\t\t\t\t\tonDragStart={ imperativeFocalPointPreview }\n\t\t\t\t\t\t\tonDrag={ imperativeFocalPointPreview }\n\t\t\t\t\t\t\tonChange={ ( newFocalPoint ) =>\n\t\t\t\t\t\t\t\tsetAttributes( {\n\t\t\t\t\t\t\t\t\tfocalPoint: newFocalPoint,\n\t\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t/>\n\t\t\t\t\t</ToolsPanelItem>\n\t\t\t\t) }\n\t\t\t</InspectorControls>\n\t\t\t{ !! imageSizeOptions.length && (\n\t\t\t\t<InspectorControls>\n\t\t\t\t\t<ToolsPanel\n\t\t\t\t\t\tlabel={ __( 'Settings' ) }\n\t\t\t\t\t\tresetAll={ resetSettings }\n\t\t\t\t\t\tdropdownMenuProps={ dropdownMenuProps }\n\t\t\t\t\t>\n\t\t\t\t\t\t<ResolutionTool\n\t\t\t\t\t\t\tvalue={ sizeSlug }\n\t\t\t\t\t\t\tdefaultValue={ DEFAULT_MEDIA_SIZE_SLUG }\n\t\t\t\t\t\t\tonChange={ updateImage }\n\t\t\t\t\t\t\toptions={ imageSizeOptions }\n\t\t\t\t\t\t/>\n\t\t\t\t\t</ToolsPanel>\n\t\t\t\t</InspectorControls>\n\t\t\t) }\n\t\t\t<InspectorControls group=\"advanced\">\n\t\t\t\t<TextControl\n\t\t\t\t\t__next40pxDefaultSize\n\t\t\t\t\tlabel={ __( 'Title attribute' ) }\n\t\t\t\t\tvalue={ title || '' }\n\t\t\t\t\tonChange={ onSetTitle }\n\t\t\t\t\treadOnly={ lockTitleControls }\n\t\t\t\t\thelp={\n\t\t\t\t\t\tlockTitleControls ? (\n\t\t\t\t\t\t\t<>{ lockTitleControlsMessage }</>\n\t\t\t\t\t\t) : (\n\t\t\t\t\t\t\t<>\n\t\t\t\t\t\t\t\t{ __(\n\t\t\t\t\t\t\t\t\t'Describe the role of this image on the page.'\n\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t<ExternalLink href=\"https://www.w3.org/TR/html52/dom.html#the-title-attribute\">\n\t\t\t\t\t\t\t\t\t{ __(\n\t\t\t\t\t\t\t\t\t\t'(Note: many devices and browsers do not display this text.)'\n\t\t\t\t\t\t\t\t\t) }\n\t\t\t\t\t\t\t\t</ExternalLink>\n\t\t\t\t\t\t\t</>\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t/>\n\t\t\t</InspectorControls>\n\t\t</>\n\t);\n\n\tconst filename = getFilename( url );\n\tlet defaultedAlt;\n\n\tif ( alt ) {\n\t\tdefaultedAlt = alt;\n\t} else if ( filename ) {\n\t\tdefaultedAlt = sprintf(\n\t\t\t/* translators: %s: file name */\n\t\t\t__( 'This image has an empty alt attribute; its file name is %s' ),\n\t\t\tfilename\n\t\t);\n\t} else {\n\t\tdefaultedAlt = __( 'This image has an empty alt attribute' );\n\t}\n\n\tconst borderProps = useBorderProps( attributes );\n\tconst shadowProps = getShadowClassesAndStyles( attributes );\n\tconst isRounded = attributes.className?.includes( 'is-style-rounded' );\n\n\tconst { postType, postId, queryId } = context;\n\tconst isDescendentOfQueryLoop = Number.isFinite( queryId );\n\n\tlet img =\n\t\ttemporaryURL && hasImageErrored ? (\n\t\t\t// Show a placeholder during upload when the blob URL can't be loaded. This can\n\t\t\t// happen when the user uploads a HEIC image in a browser that doesn't support them.\n\t\t\t<Placeholder\n\t\t\t\tclassName=\"wp-block-image__placeholder\"\n\t\t\t\twithIllustration\n\t\t\t>\n\t\t\t\t<Spinner />\n\t\t\t</Placeholder>\n\t\t) : (\n\t\t\t<>\n\t\t\t\t<img\n\t\t\t\t\tsrc={ temporaryURL || url }\n\t\t\t\t\talt={ defaultedAlt }\n\t\t\t\t\tonError={ onImageError }\n\t\t\t\t\tonLoad={ onImageLoad }\n\t\t\t\t\tref={ setRefs }\n\t\t\t\t\tclassName={ borderProps.className }\n\t\t\t\t\twidth={ naturalWidth }\n\t\t\t\t\theight={ naturalHeight }\n\t\t\t\t\tstyle={ {\n\t\t\t\t\t\taspectRatio,\n\t\t\t\t\t\t...( resizeDelta\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\twidth: pixelSize.width + resizeDelta.width,\n\t\t\t\t\t\t\t\t\theight:\n\t\t\t\t\t\t\t\t\t\tpixelSize.height + resizeDelta.height,\n\t\t\t\t\t\t\t }\n\t\t\t\t\t\t\t: { width, height } ),\n\t\t\t\t\t\tobjectFit: scale,\n\t\t\t\t\t\tobjectPosition:\n\t\t\t\t\t\t\tfocalPoint && scale\n\t\t\t\t\t\t\t\t? mediaPosition( focalPoint )\n\t\t\t\t\t\t\t\t: undefined,\n\t\t\t\t\t\t...borderProps.style,\n\t\t\t\t\t\t...shadowProps.style,\n\t\t\t\t\t} }\n\t\t\t\t/>\n\t\t\t\t{ temporaryURL && <Spinner /> }\n\t\t\t</>\n\t\t);\n\n\tif ( canEditImage && isEditingImage ) {\n\t\timg = (\n\t\t\t<ImageWrapper href={ href }>\n\t\t\t\t<ImageEditor\n\t\t\t\t\tid={ id }\n\t\t\t\t\turl={ url }\n\t\t\t\t\t{ ...pixelSize }\n\t\t\t\t\tnaturalHeight={ naturalHeight }\n\t\t\t\t\tnaturalWidth={ naturalWidth }\n\t\t\t\t\tonSaveImage={ ( imageAttributes ) =>\n\t\t\t\t\t\tsetAttributes( imageAttributes )\n\t\t\t\t\t}\n\t\t\t\t\tonFinishEditing={ () => {\n\t\t\t\t\t\tsetIsEditingImage( false );\n\t\t\t\t\t} }\n\t\t\t\t\tborderProps={ isRounded ? undefined : borderProps }\n\t\t\t\t/>\n\t\t\t</ImageWrapper>\n\t\t);\n\t} else {\n\t\timg = <ImageWrapper href={ href }>{ img }</ImageWrapper>;\n\t}\n\n\tlet resizableBox;\n\tif (\n\t\tisResizable &&\n\t\tisSingleSelected &&\n\t\t! isEditingImage &&\n\t\t! SIZED_LAYOUTS.includes( parentLayoutType )\n\t) {\n\t\tconst numericRatio = aspectRatio && evalAspectRatio( aspectRatio );\n\t\tconst customRatio = pixelSize.width / pixelSize.height;\n\t\tconst naturalRatio = naturalWidth / naturalHeight;\n\t\tconst ratio = numericRatio || customRatio || naturalRatio || 1;\n\t\tconst minWidth =\n\t\t\tnaturalWidth < naturalHeight ? MIN_SIZE : MIN_SIZE * ratio;\n\t\tconst minHeight =\n\t\t\tnaturalHeight < naturalWidth ? MIN_SIZE : MIN_SIZE / ratio;\n\n\t\t// With the current implementation of ResizableBox, an image needs an\n\t\t// explicit pixel value for the max-width. In absence of being able to\n\t\t// set the content-width, this max-width is currently dictated by the\n\t\t// vanilla editor style. The following variable adds a buffer to this\n\t\t// vanilla style, so 3rd party themes have some wiggleroom. This does,\n\t\t// in most cases, allow you to scale the image beyond the width of the\n\t\t// main column, though not infinitely.\n\t\t// @todo It would be good to revisit this once a content-width variable\n\t\t// becomes available.\n\t\tconst maxWidthBuffer = maxWidth * 2.5;\n\t\tconst maxResizeWidth = maxContentWidth || maxWidthBuffer;\n\n\t\tlet showRightHandle = false;\n\t\tlet showLeftHandle = false;\n\n\t\t/* eslint-disable no-lonely-if */\n\t\t// See https://github.com/WordPress/gutenberg/issues/7584.\n\t\tif ( align === 'center' ) {\n\t\t\t// When the image is centered, show both handles.\n\t\t\tshowRightHandle = true;\n\t\t\tshowLeftHandle = true;\n\t\t} else if ( isRTL() ) {\n\t\t\t// In RTL mode the image is on the right by default.\n\t\t\t// Show the right handle and hide the left handle only when it is\n\t\t\t// aligned left. Otherwise always show the left handle.\n\t\t\tif ( align === 'left' ) {\n\t\t\t\tshowRightHandle = true;\n\t\t\t} else {\n\t\t\t\tshowLeftHandle = true;\n\t\t\t}\n\t\t} else {\n\t\t\t// Show the left handle and hide the right handle only when the\n\t\t\t// image is aligned right. Otherwise always show the right handle.\n\t\t\tif ( align === 'right' ) {\n\t\t\t\tshowLeftHandle = true;\n\t\t\t} else {\n\t\t\t\tshowRightHandle = true;\n\t\t\t}\n\t\t}\n\t\t/* eslint-enable no-lonely-if */\n\t\tresizableBox = (\n\t\t\t<ResizableBox\n\t\t\t\tref={ effectResizeableBoxPlacement }\n\t\t\t\tstyle={ {\n\t\t\t\t\tposition: 'absolute',\n\t\t\t\t\t// To match the vertical-align: bottom of the img (from style.scss)\n\t\t\t\t\t// syncs the top with the img. This matters when the img height is\n\t\t\t\t\t// less than the line-height.\n\t\t\t\t\tinset: `${ offsetTop }px 0 0 0`,\n\t\t\t\t} }\n\t\t\t\tsize={ pixelSize }\n\t\t\t\tminWidth={ minWidth }\n\t\t\t\tmaxWidth={ maxResizeWidth }\n\t\t\t\tminHeight={ minHeight }\n\t\t\t\tmaxHeight={ maxResizeWidth / ratio }\n\t\t\t\tlockAspectRatio={ ratio }\n\t\t\t\tenable={ {\n\t\t\t\t\ttop: false,\n\t\t\t\t\tright: showRightHandle,\n\t\t\t\t\tbottom: true,\n\t\t\t\t\tleft: showLeftHandle,\n\t\t\t\t} }\n\t\t\t\tonResizeStart={ () => {\n\t\t\t\t\ttoggleSelection( false );\n\t\t\t\t} }\n\t\t\t\tonResize={ ( event, direction, elt, delta ) => {\n\t\t\t\t\tsetResizeDelta( delta );\n\t\t\t\t} }\n\t\t\t\tonResizeStop={ ( event, direction, elt, delta ) => {\n\t\t\t\t\ttoggleSelection( true );\n\t\t\t\t\tsetResizeDelta( null );\n\t\t\t\t\tsetPixelSize( ( current ) => ( {\n\t\t\t\t\t\twidth: current.width + delta.width,\n\t\t\t\t\t\theight: current.height + delta.height,\n\t\t\t\t\t} ) );\n\n\t\t\t\t\t// Clear hardcoded width if the resized width is close to the max-content width.\n\t\t\t\t\tif (\n\t\t\t\t\t\tmaxContentWidth &&\n\t\t\t\t\t\t// Only do this if the image is bigger than the container to prevent it from being squished.\n\t\t\t\t\t\t// TODO: Remove this check if the image support setting 100% width.\n\t\t\t\t\t\tnaturalWidth >= maxContentWidth &&\n\t\t\t\t\t\tMath.abs( elt.offsetWidth - maxContentWidth ) < 10\n\t\t\t\t\t) {\n\t\t\t\t\t\tsetAttributes( {\n\t\t\t\t\t\t\twidth: undefined,\n\t\t\t\t\t\t\theight: undefined,\n\t\t\t\t\t\t} );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Since the aspect ratio is locked when resizing, we can\n\t\t\t\t\t// use the width of the resized element to calculate the\n\t\t\t\t\t// height in CSS to prevent stretching when the max-width\n\t\t\t\t\t// is reached.\n\t\t\t\t\tsetAttributes( {\n\t\t\t\t\t\twidth: `${ elt.offsetWidth }px`,\n\t\t\t\t\t\theight: 'auto',\n\t\t\t\t\t\taspectRatio:\n\t\t\t\t\t\t\tratio === naturalRatio\n\t\t\t\t\t\t\t\t? undefined\n\t\t\t\t\t\t\t\t: String( ratio ),\n\t\t\t\t\t} );\n\t\t\t\t} }\n\t\t\t\tresizeRatio={ align === 'center' ? 2 : 1 }\n\t\t\t/>\n\t\t);\n\t}\n\n\tif ( ! url && ! temporaryURL ) {\n\t\treturn (\n\t\t\t<>\n\t\t\t\t{ mediaReplaceFlow }\n\t\t\t\t{ controls }\n\t\t\t</>\n\t\t);\n\t}\n\n\t/**\n\t * Set the post's featured image with the current image.\n\t */\n\tconst setPostFeatureImage = () => {\n\t\teditEntityRecord( 'postType', postType, postId, {\n\t\t\tfeatured_media: id,\n\t\t} );\n\t\tcreateSuccessNotice( __( 'Post featured image updated.' ), {\n\t\t\ttype: 'snackbar',\n\t\t} );\n\t};\n\n\tconst featuredImageControl = (\n\t\t<BlockSettingsMenuControls>\n\t\t\t{ ( { selectedClientIds } ) =>\n\t\t\t\tselectedClientIds.length === 1 &&\n\t\t\t\t! isDescendentOfQueryLoop &&\n\t\t\t\tpostId &&\n\t\t\t\tid &&\n\t\t\t\tclientId === selectedClientIds[ 0 ] && (\n\t\t\t\t\t<MenuItem onClick={ setPostFeatureImage }>\n\t\t\t\t\t\t{ __( 'Set as featured image' ) }\n\t\t\t\t\t</MenuItem>\n\t\t\t\t)\n\t\t\t}\n\t\t</BlockSettingsMenuControls>\n\t);\n\n\treturn (\n\t\t<>\n\t\t\t{ editMediaButton }\n\t\t\t{ mediaReplaceFlow }\n\t\t\t{ controls }\n\t\t\t{ featuredImageControl }\n\t\t\t{ img }\n\t\t\t{ resizableBox }\n\n\t\t\t<Caption\n\t\t\t\tattributes={ attributes }\n\t\t\t\tsetAttributes={ setAttributes }\n\t\t\t\tisSelected={ isSingleSelected }\n\t\t\t\tinsertBlocksAfter={ insertBlocksAfter }\n\t\t\t\tlabel={ __( 'Image caption text' ) }\n\t\t\t\tshowToolbarButton={\n\t\t\t\t\tisSingleSelected &&\n\t\t\t\t\t( hasNonContentControls || isContentOnlyMode ) &&\n\t\t\t\t\t! hideCaptionControls\n\t\t\t\t}\n\t\t\t/>\n\t\t</>\n\t);\n}\n"],
"mappings": "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