@wordpress/block-library
Version:
Block library for the WordPress editor.
318 lines (301 loc) • 7.79 kB
JavaScript
/**
* WordPress dependencies
*/
import { Fragment, useMemo } from '@wordpress/element';
import {
BaseControl,
Button,
ExternalLink,
FocalPointPicker,
PanelBody,
PanelRow,
RangeControl,
TextareaControl,
ToggleControl,
__experimentalUseCustomUnits as useCustomUnits,
__experimentalToolsPanelItem as ToolsPanelItem,
__experimentalUnitControl as UnitControl,
__experimentalParseQuantityAndUnitFromRawValue as parseQuantityAndUnitFromRawValue,
} from '@wordpress/components';
import { useInstanceId } from '@wordpress/compose';
import {
InspectorControls,
useSetting,
__experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown,
__experimentalUseGradient,
__experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients,
} from '@wordpress/block-editor';
import { __ } from '@wordpress/i18n';
/**
* Internal dependencies
*/
import { COVER_MIN_HEIGHT, mediaPosition } from '../shared';
function CoverHeightInput( {
onChange,
onUnitChange,
unit = 'px',
value = '',
} ) {
const instanceId = useInstanceId( UnitControl );
const inputId = `block-cover-height-input-${ instanceId }`;
const isPx = unit === 'px';
const units = useCustomUnits( {
availableUnits: useSetting( 'spacing.units' ) || [
'px',
'em',
'rem',
'vw',
'vh',
],
defaultValues: { px: 430, '%': 20, em: 20, rem: 20, vw: 20, vh: 50 },
} );
const handleOnChange = ( unprocessedValue ) => {
const inputValue =
unprocessedValue !== ''
? parseFloat( unprocessedValue )
: undefined;
if ( isNaN( inputValue ) && inputValue !== undefined ) {
return;
}
onChange( inputValue );
};
const computedValue = useMemo( () => {
const [ parsedQuantity ] = parseQuantityAndUnitFromRawValue( value );
return [ parsedQuantity, unit ].join( '' );
}, [ unit, value ] );
const min = isPx ? COVER_MIN_HEIGHT : 0;
return (
<BaseControl label={ __( 'Minimum height of cover' ) } id={ inputId }>
<UnitControl
id={ inputId }
isResetValueOnUnitChange
min={ min }
onChange={ handleOnChange }
onUnitChange={ onUnitChange }
style={ { maxWidth: 80 } }
units={ units }
value={ computedValue }
/>
</BaseControl>
);
}
export default function CoverInspectorControls( {
attributes,
setAttributes,
clientId,
setOverlayColor,
coverRef,
currentSettings,
} ) {
const {
useFeaturedImage,
dimRatio,
focalPoint,
hasParallax,
isRepeated,
minHeight,
minHeightUnit,
alt,
} = attributes;
const {
isVideoBackground,
isImageBackground,
mediaElement,
url,
isImgElement,
overlayColor,
} = currentSettings;
const { gradientValue, setGradient } = __experimentalUseGradient();
const toggleParallax = () => {
setAttributes( {
hasParallax: ! hasParallax,
...( ! hasParallax ? { focalPoint: undefined } : {} ),
} );
};
const toggleIsRepeated = () => {
setAttributes( {
isRepeated: ! isRepeated,
} );
};
const showFocalPointPicker =
isVideoBackground ||
( isImageBackground && ( ! hasParallax || isRepeated ) );
const imperativeFocalPointPreview = ( value ) => {
const [ styleOfRef, property ] = mediaElement.current
? [ mediaElement.current.style, 'objectPosition' ]
: [ coverRef.current.style, 'backgroundPosition' ];
styleOfRef[ property ] = mediaPosition( value );
};
const colorGradientSettings = useMultipleOriginColorsAndGradients();
return (
<>
<InspectorControls>
{ !! url && (
<PanelBody title={ __( 'Media settings' ) }>
{ isImageBackground && (
<Fragment>
<ToggleControl
label={ __( 'Fixed background' ) }
checked={ hasParallax }
onChange={ toggleParallax }
/>
<ToggleControl
label={ __( 'Repeated background' ) }
checked={ isRepeated }
onChange={ toggleIsRepeated }
/>
</Fragment>
) }
{ showFocalPointPicker && (
<FocalPointPicker
label={ __( 'Focal point picker' ) }
url={ url }
value={ focalPoint }
onDragStart={ imperativeFocalPointPreview }
onDrag={ imperativeFocalPointPreview }
onChange={ ( newFocalPoint ) =>
setAttributes( {
focalPoint: newFocalPoint,
} )
}
/>
) }
{ ! useFeaturedImage &&
url &&
isImageBackground &&
isImgElement && (
<TextareaControl
label={ __(
'Alt text (alternative text)'
) }
value={ alt }
onChange={ ( newAlt ) =>
setAttributes( { alt: newAlt } )
}
help={
<>
<ExternalLink href="https://www.w3.org/WAI/tutorials/images/decision-tree">
{ __(
'Describe the purpose of the image'
) }
</ExternalLink>
{ __(
'Leave empty if the image is purely decorative.'
) }
</>
}
/>
) }
<PanelRow>
<Button
variant="secondary"
isSmall
className="block-library-cover__reset-button"
onClick={ () =>
setAttributes( {
url: undefined,
id: undefined,
backgroundType: undefined,
focalPoint: undefined,
hasParallax: undefined,
isRepeated: undefined,
useFeaturedImage: false,
} )
}
>
{ __( 'Clear Media' ) }
</Button>
</PanelRow>
</PanelBody>
) }
</InspectorControls>
<InspectorControls __experimentalGroup="color">
<ColorGradientSettingsDropdown
__experimentalHasMultipleOrigins
__experimentalIsRenderedInSidebar
settings={ [
{
colorValue: overlayColor.color,
gradientValue,
label: __( 'Overlay' ),
onColorChange: setOverlayColor,
onGradientChange: setGradient,
isShownByDefault: true,
resetAllFilter: () => ( {
overlayColor: undefined,
customOverlayColor: undefined,
gradient: undefined,
customGradient: undefined,
} ),
},
] }
panelId={ clientId }
{ ...colorGradientSettings }
/>
<ToolsPanelItem
hasValue={ () => {
// If there's a media background the dimRatio will be
// defaulted to 50 whereas it will be 100 for colors.
return dimRatio === undefined
? false
: dimRatio !== ( url ? 50 : 100 );
} }
label={ __( 'Overlay opacity' ) }
onDeselect={ () =>
setAttributes( { dimRatio: url ? 50 : 100 } )
}
resetAllFilter={ () => ( {
dimRatio: url ? 50 : 100,
} ) }
isShownByDefault
panelId={ clientId }
>
<RangeControl
label={ __( 'Overlay opacity' ) }
value={ dimRatio }
onChange={ ( newDimRation ) =>
setAttributes( {
dimRatio: newDimRation,
} )
}
min={ 0 }
max={ 100 }
step={ 10 }
required
/>
</ToolsPanelItem>
</InspectorControls>
<InspectorControls __experimentalGroup="dimensions">
<ToolsPanelItem
hasValue={ () => !! minHeight }
label={ __( 'Minimum height' ) }
onDeselect={ () =>
setAttributes( {
minHeight: undefined,
minHeightUnit: undefined,
} )
}
resetAllFilter={ () => ( {
minHeight: undefined,
minHeightUnit: undefined,
} ) }
isShownByDefault={ true }
panelId={ clientId }
>
<CoverHeightInput
value={ minHeight }
unit={ minHeightUnit }
onChange={ ( newMinHeight ) =>
setAttributes( { minHeight: newMinHeight } )
}
onUnitChange={ ( nextUnit ) =>
setAttributes( {
minHeightUnit: nextUnit,
} )
}
/>
</ToolsPanelItem>
</InspectorControls>
</>
);
}