@@ -22,6 +22,8 @@ import {
2222 __experimentalItemGroup as ItemGroup ,
2323 __experimentalHStack as HStack ,
2424 __experimentalTruncate as Truncate ,
25+ Dropdown ,
26+ __experimentalDropdownContentWrapper as DropdownContentWrapper ,
2527} from '@wordpress/components' ;
2628import { __ , sprintf } from '@wordpress/i18n' ;
2729import { store as noticesStore } from '@wordpress/notices' ;
@@ -30,6 +32,7 @@ import { useCallback, Platform, useRef } from '@wordpress/element';
3032import { useDispatch , useSelect } from '@wordpress/data' ;
3133import { focus } from '@wordpress/dom' ;
3234import { isBlobURL } from '@wordpress/blob' ;
35+ import { reusableBlock , Icon } from '@wordpress/icons' ;
3336
3437/**
3538 * Internal dependencies
@@ -41,6 +44,12 @@ import { store as blockEditorStore } from '../../store';
4144
4245const IMAGE_BACKGROUND_TYPE = 'image' ;
4346
47+ const BACKGROUND_POPOVER_PROPS = {
48+ placement : 'left-start' ,
49+ offset : 36 ,
50+ shift : true ,
51+ } ;
52+
4453/**
4554 * Checks site settings to see if the background panel may be used.
4655 * `settings.background.backgroundSize` exists also,
@@ -134,10 +143,142 @@ export const backgroundPositionToCoords = ( value ) => {
134143 return { x, y } ;
135144} ;
136145
137- function InspectorImagePreview ( { label, filename, url : imgUrl } ) {
146+ function InspectorImagePreviewToggle ( {
147+ label,
148+ filename,
149+ url : imgUrl ,
150+ children,
151+ allowPopover = false ,
152+ } ) {
138153 const imgLabel = label || getFilename ( imgUrl ) ;
154+ // @TODO abstract
155+ if ( ! allowPopover ) {
156+ return (
157+ < ItemGroup
158+ as = "span"
159+ className = "block-editor-global-styles-background-panel__image-preview"
160+ >
161+ < HStack
162+ justify = "flex-start"
163+ as = "span"
164+ className = "block-editor-global-styles-background-panel__image-preview-content"
165+ >
166+ < span
167+ className = { classnames (
168+ 'block-editor-global-styles-background-panel__inspector-image-indicator-wrapper' ,
169+ {
170+ 'has-image' : imgUrl ,
171+ }
172+ ) }
173+ aria-hidden
174+ >
175+ { imgUrl && (
176+ < span
177+ className = "block-editor-global-styles-background-panel__inspector-image-indicator"
178+ style = { {
179+ backgroundImage : `url(${ imgUrl } )` ,
180+ } }
181+ />
182+ ) }
183+ </ span >
184+ < FlexItem as = "span" >
185+ < Truncate
186+ numberOfLines = { 1 }
187+ className = "block-editor-global-styles-background-panel__inspector-media-replace-title"
188+ >
189+ { imgLabel }
190+ </ Truncate >
191+ < VisuallyHidden as = "span" >
192+ { filename
193+ ? sprintf (
194+ /* translators: %s: file name */
195+ __ ( 'Selected image: %s' ) ,
196+ filename
197+ )
198+ : __ ( 'No image selected' ) }
199+ </ VisuallyHidden >
200+ </ FlexItem >
201+ </ HStack >
202+ </ ItemGroup >
203+ ) ;
204+ }
139205 return (
140- < ItemGroup as = "span" >
206+ < Dropdown
207+ popoverProps = { BACKGROUND_POPOVER_PROPS }
208+ className = "block-editor-global-styles-background-panel__inspector-media-replace"
209+ renderToggle = { ( { onToggle, isOpen } ) => {
210+ const toggleProps = {
211+ onClick : onToggle ,
212+ className : classnames (
213+ 'block-editor-global-styles-background-panel__dropdown-toggle' ,
214+ { 'is-open' : isOpen }
215+ ) ,
216+ 'aria-expanded' : isOpen ,
217+ 'aria-label' : __ (
218+ 'Background size, position and repeat options.'
219+ ) ,
220+ } ;
221+ return (
222+ < ItemGroup as = "button" { ...toggleProps } >
223+ < HStack justify = "flex-start" as = "span" >
224+ < span
225+ className = { classnames (
226+ 'block-editor-global-styles-background-panel__inspector-image-indicator-wrapper' ,
227+ {
228+ 'has-image' : imgUrl ,
229+ }
230+ ) }
231+ aria-hidden
232+ >
233+ { imgUrl && (
234+ < span
235+ className = "block-editor-global-styles-background-panel__inspector-image-indicator"
236+ style = { {
237+ backgroundImage : `url(${ imgUrl } )` ,
238+ } }
239+ />
240+ ) }
241+ </ span >
242+ < FlexItem as = "span" >
243+ < Truncate
244+ numberOfLines = { 1 }
245+ className = "block-editor-global-styles-background-panel__inspector-media-replace-title"
246+ >
247+ { imgLabel }
248+ </ Truncate >
249+ < VisuallyHidden as = "span" >
250+ { filename
251+ ? sprintf (
252+ /* translators: %s: file name */
253+ __ ( 'Selected image: %s' ) ,
254+ filename
255+ )
256+ : __ ( 'No image selected' ) }
257+ </ VisuallyHidden >
258+ </ FlexItem >
259+ </ HStack >
260+ </ ItemGroup >
261+ ) ;
262+ } }
263+ renderContent = { ( { onClose } ) => (
264+ < DropdownContentWrapper > { children } </ DropdownContentWrapper >
265+ ) }
266+ />
267+ ) ;
268+ }
269+
270+ function InspectorImagePreview ( {
271+ label,
272+ title,
273+ url : imgUrl ,
274+ //as = 'span',
275+ //className = 'block-editor-global-styles-background-panel__image-preview',
276+ ...otherProps
277+ } ) {
278+ const imgLabel = label || getFilename ( imgUrl ) || __ ( 'Add image' ) ;
279+ const filename = title || __ ( 'Unitled' ) ;
280+ return (
281+ < ItemGroup { ...otherProps } >
141282 < HStack justify = "flex-start" as = "span" >
142283 < span
143284 className = { classnames (
@@ -179,12 +320,71 @@ function InspectorImagePreview( { label, filename, url: imgUrl } ) {
179320 ) ;
180321}
181322
323+ function BackgroundImageControls ( {
324+ hasImageValue,
325+ settings,
326+ url,
327+ title,
328+ children,
329+ } ) {
330+ const shouldShowBackgroundSizeControls =
331+ hasImageValue &&
332+ ( settings ?. background ?. backgroundSize ||
333+ settings ?. background ?. backgroundPosition ||
334+ settings ?. background ?. backgroundRepeat ) ;
335+
336+ if ( ! shouldShowBackgroundSizeControls ) {
337+ return (
338+ < InspectorImagePreview
339+ label = { title }
340+ url = { url }
341+ as = "span"
342+ className = "block-editor-global-styles-background-panel__image-preview"
343+ />
344+ ) ;
345+ }
346+
347+ return (
348+ < Dropdown
349+ popoverProps = { BACKGROUND_POPOVER_PROPS }
350+ className = "block-editor-global-styles-background-panel__inspector-media-replace"
351+ renderToggle = { ( { onToggle, isOpen } ) => {
352+ const toggleProps = {
353+ onClick : onToggle ,
354+ className : classnames (
355+ 'block-editor-global-styles-background-panel__dropdown-toggle' ,
356+ { 'is-open' : isOpen }
357+ ) ,
358+ 'aria-expanded' : isOpen ,
359+ 'aria-label' : __ (
360+ 'Background size, position and repeat options.'
361+ ) ,
362+ } ;
363+ return (
364+ < InspectorImagePreview
365+ label = { title }
366+ filename = { title }
367+ url = { url }
368+ as = { 'button' }
369+ { ...toggleProps }
370+ />
371+ ) ;
372+ } }
373+ renderContent = { ( ) => (
374+ < DropdownContentWrapper > { children } </ DropdownContentWrapper >
375+ ) }
376+ />
377+ ) ;
378+ }
379+
182380function BackgroundImageToolsPanelItem ( {
183381 panelId,
184- isShownByDefault ,
382+ defaultControls ,
185383 onChange,
186384 style,
187385 inheritedValue,
386+ defaultValues,
387+ settings,
188388} ) {
189389 const mediaUpload = useSelect (
190390 ( select ) => select ( blockEditorStore ) . getSettings ( ) . mediaUpload ,
@@ -273,33 +473,48 @@ function BackgroundImageToolsPanelItem( {
273473 hasBackgroundImageValue ( style ) ||
274474 hasBackgroundImageValue ( inheritedValue ) ;
275475
476+ const shouldShowBackgroundImageControls =
477+ hasValue &&
478+ ( settings ?. background ?. backgroundSize ||
479+ settings ?. background ?. backgroundPosition ||
480+ settings ?. background ?. backgroundRepeat ) ;
481+
276482 return (
277483 < ToolsPanelItem
278484 className = "single-column"
279485 hasValue = { ( ) => hasValue }
280486 label = { __ ( 'Background image' ) }
281487 onDeselect = { resetBackgroundImage }
282- isShownByDefault = { isShownByDefault }
488+ isShownByDefault = { defaultControls . backgroundImage }
283489 resetAllFilter = { resetAllFilter }
284490 panelId = { panelId }
285491 >
286492 < div
287493 className = "block-editor-global-styles-background-panel__inspector-media-replace-container"
288494 ref = { replaceContainerRef }
289495 >
496+ < InspectorImagePreviewToggle
497+ label = { __ ( 'Background image' ) }
498+ filename = { title || __ ( 'Untitled' ) }
499+ url = { url }
500+ allowPopover = { shouldShowBackgroundImageControls }
501+ >
502+ < BackgroundSizeToolsPanelItem
503+ onChange = { onChange }
504+ panelId = { panelId }
505+ defaultControls = { defaultControls }
506+ style = { style }
507+ inheritedValue = { inheritedValue }
508+ defaultValues = { defaultValues }
509+ />
510+ </ InspectorImagePreviewToggle >
290511 < MediaReplaceFlow
291512 mediaId = { id }
292513 mediaURL = { url }
293514 allowedTypes = { [ IMAGE_BACKGROUND_TYPE ] }
294515 accept = "image/*"
295516 onSelect = { onSelectMedia }
296- name = {
297- < InspectorImagePreview
298- label = { __ ( 'Background image' ) }
299- filename = { title || __ ( 'Untitled' ) }
300- url = { url }
301- />
302- }
517+ name = { < Icon icon = { reusableBlock } /> }
303518 variant = "secondary"
304519 >
305520 { hasValue && (
@@ -331,11 +546,11 @@ function BackgroundImageToolsPanelItem( {
331546
332547function BackgroundSizeToolsPanelItem ( {
333548 panelId,
334- isShownByDefault,
335549 onChange,
336550 style,
337551 inheritedValue,
338552 defaultValues,
553+ defaultControls,
339554} ) {
340555 const sizeValue =
341556 style ?. background ?. backgroundSize ||
@@ -457,8 +672,8 @@ function BackgroundSizeToolsPanelItem( {
457672 hasValue = { ( ) => hasValue }
458673 label = { __ ( 'Size' ) }
459674 onDeselect = { resetBackgroundSize }
460- isShownByDefault = { isShownByDefault }
461675 resetAllFilter = { resetAllFilter }
676+ isShownByDefault = { defaultControls . backgroundSize }
462677 panelId = { panelId }
463678 >
464679 < FocalPointPicker
@@ -559,8 +774,6 @@ export default function BackgroundPanel( {
559774 background : { } ,
560775 } ;
561776 } , [ ] ) ;
562- const shouldShowBackgroundSizeControls =
563- settings ?. background ?. backgroundSize ;
564777
565778 return (
566779 < Wrapper
@@ -572,20 +785,12 @@ export default function BackgroundPanel( {
572785 < BackgroundImageToolsPanelItem
573786 onChange = { onChange }
574787 panelId = { panelId }
575- isShownByDefault = { defaultControls . backgroundImage }
788+ defaultControls = { defaultControls }
576789 style = { value }
577790 inheritedValue = { inheritedValue }
791+ defaultValues = { defaultValues }
792+ settings = { settings }
578793 />
579- { shouldShowBackgroundSizeControls && (
580- < BackgroundSizeToolsPanelItem
581- onChange = { onChange }
582- panelId = { panelId }
583- isShownByDefault = { defaultControls . backgroundSize }
584- style = { value }
585- inheritedValue = { inheritedValue }
586- defaultValues = { defaultValues }
587- />
588- ) }
589794 </ Wrapper >
590795 ) ;
591796}
0 commit comments