@wordpress/block-library
Version:
Block library for the WordPress editor.
270 lines (250 loc) • 7.17 kB
JavaScript
/**
* External dependencies
*/
import classNames from 'classnames';
/**
* WordPress dependencies
*/
import { getBlockSupport } from '@wordpress/blocks';
import { useEffect, useRef } from '@wordpress/element';
import {
BlockControls,
useInnerBlocksProps,
useBlockProps,
InspectorControls,
ContrastChecker,
withColors,
__experimentalColorGradientSettingsDropdown as ColorGradientSettingsDropdown,
__experimentalUseMultipleOriginColorsAndGradients as useMultipleOriginColorsAndGradients,
} from '@wordpress/block-editor';
import {
MenuGroup,
MenuItem,
PanelBody,
ToggleControl,
ToolbarDropdownMenu,
} from '@wordpress/components';
import { __ } from '@wordpress/i18n';
import { check } from '@wordpress/icons';
const ALLOWED_BLOCKS = [ 'core/social-link' ];
const sizeOptions = [
{ name: __( 'Small' ), value: 'has-small-icon-size' },
{ name: __( 'Normal' ), value: 'has-normal-icon-size' },
{ name: __( 'Large' ), value: 'has-large-icon-size' },
{ name: __( 'Huge' ), value: 'has-huge-icon-size' },
];
const getDefaultBlockLayout = ( blockTypeOrName ) => {
const layoutBlockSupportConfig = getBlockSupport(
blockTypeOrName,
'__experimentalLayout'
);
return layoutBlockSupportConfig?.default;
};
export function SocialLinksEdit( props ) {
const {
clientId,
name,
attributes,
iconBackgroundColor,
iconColor,
isSelected,
setAttributes,
setIconBackgroundColor,
setIconColor,
} = props;
const {
iconBackgroundColorValue,
customIconBackgroundColor,
iconColorValue,
openInNewTab,
showLabels,
size,
layout,
} = attributes;
const usedLayout = layout || getDefaultBlockLayout( name );
const logosOnly = attributes.className?.includes( 'is-style-logos-only' );
// Remove icon background color when logos only style is selected or
// restore it when any other style is selected.
const backgroundBackup = useRef( {} );
useEffect( () => {
if ( logosOnly ) {
backgroundBackup.current = {
iconBackgroundColor,
iconBackgroundColorValue,
customIconBackgroundColor,
};
setAttributes( {
iconBackgroundColor: undefined,
customIconBackgroundColor: undefined,
iconBackgroundColorValue: undefined,
} );
} else {
setAttributes( { ...backgroundBackup.current } );
}
}, [ logosOnly ] );
const SocialPlaceholder = (
<li className="wp-block-social-links__social-placeholder">
<div className="wp-block-social-links__social-placeholder-icons">
<div className="wp-social-link wp-social-link-twitter"></div>
<div className="wp-social-link wp-social-link-facebook"></div>
<div className="wp-social-link wp-social-link-instagram"></div>
</div>
</li>
);
const SelectedSocialPlaceholder = (
<li className="wp-block-social-links__social-prompt">
{ __( 'Click plus to add' ) }
</li>
);
// Fallback color values are used maintain selections in case switching
// themes and named colors in palette do not match.
const className = classNames( size, {
'has-visible-labels': showLabels,
'has-icon-color': iconColor.color || iconColorValue,
'has-icon-background-color':
iconBackgroundColor.color || iconBackgroundColorValue,
} );
const blockProps = useBlockProps( { className } );
const innerBlocksProps = useInnerBlocksProps( blockProps, {
allowedBlocks: ALLOWED_BLOCKS,
placeholder: isSelected ? SelectedSocialPlaceholder : SocialPlaceholder,
templateLock: false,
__experimentalAppenderTagName: 'li',
__experimentalLayout: usedLayout,
} );
const POPOVER_PROPS = {
position: 'bottom right',
};
const colorSettings = [
{
// Use custom attribute as fallback to prevent loss of named color selection when
// switching themes to a new theme that does not have a matching named color.
value: iconColor.color || iconColorValue,
onChange: ( colorValue ) => {
setIconColor( colorValue );
setAttributes( { iconColorValue: colorValue } );
},
label: __( 'Icon color' ),
resetAllFilter: () => {
setIconColor( undefined );
setAttributes( { iconColorValue: undefined } );
},
},
];
if ( ! logosOnly ) {
colorSettings.push( {
// Use custom attribute as fallback to prevent loss of named color selection when
// switching themes to a new theme that does not have a matching named color.
value: iconBackgroundColor.color || iconBackgroundColorValue,
onChange: ( colorValue ) => {
setIconBackgroundColor( colorValue );
setAttributes( {
iconBackgroundColorValue: colorValue,
} );
},
label: __( 'Icon background' ),
resetAllFilter: () => {
setIconBackgroundColor( undefined );
setAttributes( { iconBackgroundColorValue: undefined } );
},
} );
}
const colorGradientSettings = useMultipleOriginColorsAndGradients();
return (
<>
<BlockControls group="other">
<ToolbarDropdownMenu
label={ __( 'Size' ) }
text={ __( 'Size' ) }
icon={ null }
popoverProps={ POPOVER_PROPS }
>
{ ( { onClose } ) => (
<MenuGroup>
{ sizeOptions.map( ( entry ) => {
return (
<MenuItem
icon={
( size === entry.value ||
( ! size &&
entry.value ===
'has-normal-icon-size' ) ) &&
check
}
isSelected={ size === entry.value }
key={ entry.value }
onClick={ () => {
setAttributes( {
size: entry.value,
} );
} }
onClose={ onClose }
role="menuitemradio"
>
{ entry.name }
</MenuItem>
);
} ) }
</MenuGroup>
) }
</ToolbarDropdownMenu>
</BlockControls>
<InspectorControls>
<PanelBody title={ __( 'Link settings' ) }>
<ToggleControl
label={ __( 'Open links in new tab' ) }
checked={ openInNewTab }
onChange={ () =>
setAttributes( { openInNewTab: ! openInNewTab } )
}
/>
<ToggleControl
label={ __( 'Show labels' ) }
checked={ showLabels }
onChange={ () =>
setAttributes( { showLabels: ! showLabels } )
}
/>
</PanelBody>
</InspectorControls>
<InspectorControls __experimentalGroup="color">
{ colorSettings.map(
( { onChange, label, value, resetAllFilter } ) => (
<ColorGradientSettingsDropdown
key={ `social-links-color-${ label }` }
__experimentalHasMultipleOrigins
__experimentalIsRenderedInSidebar
settings={ [
{
colorValue: value,
label,
onColorChange: onChange,
isShownByDefault: true,
resetAllFilter,
enableAlpha: true,
},
] }
panelId={ clientId }
{ ...colorGradientSettings }
/>
)
) }
{ ! logosOnly && (
<ContrastChecker
{ ...{
textColor: iconColorValue,
backgroundColor: iconBackgroundColorValue,
} }
isLargeText={ false }
/>
) }
</InspectorControls>
<ul { ...innerBlocksProps } />
</>
);
}
const iconColorAttributes = {
iconColor: 'icon-color',
iconBackgroundColor: 'icon-background-color',
};
export default withColors( iconColorAttributes )( SocialLinksEdit );