Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Social links block. #14855

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/block-library/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import {
/**
* Internal dependencies
*/
import * as socialLinks from './social-links';
import * as socialLink from './social-links/social-link';
import * as paragraph from './paragraph';
import * as image from './image';
import * as heading from './heading';
Expand Down Expand Up @@ -116,6 +118,8 @@ export const registerCoreBlocks = () => {
search,
separator,
reusableBlock,
socialLinks,
socialLink,
spacer,
subhead,
table,
Expand Down
10 changes: 10 additions & 0 deletions packages/block-library/src/social-links/block.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"name": "core/social-links",
"category": "widgets",
"attributes": {
"columns": {
"type": "number",
"default": 2
}
}
}
127 changes: 127 additions & 0 deletions packages/block-library/src/social-links/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { compose } from '@wordpress/compose';
import {
PanelBody,
RangeControl,
IconButton,
} from '@wordpress/components';
import { createBlock } from '@wordpress/blocks';
import { Fragment } from '@wordpress/element';
import {
InspectorControls,
InnerBlocks,
BlockControls,
BlockVerticalAlignmentToolbar,
} from '@wordpress/block-editor';
import { withSelect, withDispatch } from '@wordpress/data';

/**
* Internal dependencies
*/
import { getColumnsTemplate } from './utils';

/**
* Allowed blocks constant is passed to InnerBlocks precisely as specified here.
* The contents of the array should never change.
* The array should contain the name of each block that is allowed.
* In columns block, the only block we allow is 'core/column'.
*
* @constant
* @type {string[]}
*/
const ALLOWED_BLOCKS = [ 'core/social-link' ];

export const SocialLinksEdit = function( { attributes, setAttributes, className, updateAlignment, addLink } ) {
const { columns, verticalAlignment } = attributes;

const classes = classnames( className, `has-${ columns }-columns`, {
[ `are-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment,
} );

const onChange = ( alignment ) => {
// Update all the (immediate) child Column Blocks
updateAlignment( alignment );
};



return (
<Fragment>
<InspectorControls>
<PanelBody>
<RangeControl
label={ __( 'Columns' ) }
value={ columns }
onChange={ ( nextColumns ) => {
setAttributes( {
columns: nextColumns,
} );
} }
min={ 1 }
max={ 6 }
/>
</PanelBody>
</InspectorControls>
<BlockControls>
<BlockVerticalAlignmentToolbar
onChange={ onChange }
value={ verticalAlignment }
/>
</BlockControls>

<div className={ classes }>
<InnerBlocks
template={ getColumnsTemplate( columns ) }
templateLock={ 'insert' }
allowedBlocks={ ALLOWED_BLOCKS } />

<div>
<IconButton
isLarge
label={ __( 'Add link' ) }
icon="insert"
onClick={ addLink } >
{ __( 'Add link' ) }
</IconButton>
</div>
</div>
</Fragment>
);
};

const DEFAULT_EMPTY_ARRAY = [];

export default compose(
withSelect( ( select, { clientId } ) => {
const { getBlocksByClientId } = select( 'core/block-editor' );
const [ block ] = getBlocksByClientId( clientId );

return {
childLinks: block ? block.innerBlocks : DEFAULT_EMPTY_ARRAY,
};
} ),
withDispatch( ( dispatch, ownProps, registry ) => ( {
addLink() {
const { clientId } = ownProps;
const { replaceInnerBlocks } = dispatch( 'core/block-editor' );
const { getBlocks } = registry.select( 'core/block-editor' );

let innerBlocks = getBlocks( clientId );
innerBlocks = [
...innerBlocks,
createBlock( 'core/social-link', { verticalAlignment: 'top' } ),
];

replaceInnerBlocks( clientId, innerBlocks, false );
},
} )
),
)( SocialLinksEdit );
8 changes: 8 additions & 0 deletions packages/block-library/src/social-links/icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* WordPress dependencies
*/
import { G, Path, SVG } from '@wordpress/components';

export default (
<SVG viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><Path fill="none" d="M0 0h24v24H0V0z" /><G><Path d="M4,4H20a2,2,0,0,1,2,2V18a2,2,0,0,1-2,2H4a2,2,0,0,1-2-2V6A2,2,0,0,1,4,4ZM4 6V18H8V6Zm6 0V18h4V6Zm6 0V18h4V6Z" /></G></SVG>
);
33 changes: 33 additions & 0 deletions packages/block-library/src/social-links/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/**
* WordPress dependencies
*/
import { __, _x } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import edit from './edit';
import icon from './icon';
import metadata from './block.json';
import save from './save';

const { name } = metadata;

export { metadata, name };

export const settings = {
title: __( 'Social links' ),
icon,
description: __( 'Add a block that displays content in multiple columns, then add whatever content blocks you’d like.' ),
styles: [
{ name: 'regular', label: _x( 'Regular', 'block style' ), isDefault: true },
{ name: 'filled', label: __( 'Filled' ) },
],
supports: {
align: [ 'wide', 'full' ],
html: false,
},
edit,
save,
};

23 changes: 23 additions & 0 deletions packages/block-library/src/social-links/save.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { InnerBlocks } from '@wordpress/block-editor';

export default function save( { attributes } ) {
const { columns, verticalAlignment } = attributes;

const wrapperClasses = classnames( `has-${ columns }-columns`, {
[ `are-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment,
} );

return (
<div className={ wrapperClasses }>
<InnerBlocks.Content />
</div>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* WordPress dependencies
*/
import { Path, SVG } from '@wordpress/components';

export default <SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><Path d="M4 4h7V2H4c-1.1 0-2 .9-2 2v7h2V4zm6 9l-4 5h12l-3-4-2.03 2.71L10 13zm7-4.5c0-.83-.67-1.5-1.5-1.5S14 7.67 14 8.5s.67 1.5 1.5 1.5S17 9.33 17 8.5zM20 2h-7v2h7v7h2V4c0-1.1-.9-2-2-2zm0 18h-7v2h7c1.1 0 2-.9 2-2v-7h-2v7zM4 13H2v7c0 1.1.9 2 2 2h7v-2H4v-7z" /><Path d="M0 0h24v24H0z" fill="none" /></SVG>;
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"name": "core/social-link",
"category": "widgets",
"attributes": {
"url": {
"type": "string"
}
}
}
67 changes: 67 additions & 0 deletions packages/block-library/src/social-links/social-link/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';
import { Fragment } from '@wordpress/element';
import { withDispatch } from '@wordpress/data';
import { compose } from '@wordpress/compose';
import { Icon } from '@wordpress/components';

/**
* Internal dependencies
*/

import PlaceholderIcon from './PlaceholderIcon';

const SocialLinkEdit = ( { attributes, setUrl, isSelected } ) => {
const { url } = attributes;

const getDashiconsIconName = () => {
const isFacebook = url.includes( 'fb.com' ) || url.includes( 'facebook.com' );

if ( isFacebook ) {
return 'facebook';
}
};

const dashiconsIconName = getDashiconsIconName();

return (
<Fragment>
<div className={ `dashicons-before dashicons-${ dashiconsIconName }` } />

{
isSelected && (
<form >
<input
type="url"
value={ ( attributes && url ) || '' }
onChange={ ( event ) => setUrl( event.target.value ) }
placeholder={ __( 'example.com/username' ) }
/>
</form>
)
}

{ ! isSelected && url }
</Fragment>
);
};

export default compose(
withDispatch( ( _, ownProps ) => {
return {
setUrl( url ) {
const { setAttributes } = ownProps;

setAttributes( { url } );
},
};
} )
)( SocialLinkEdit );

8 changes: 8 additions & 0 deletions packages/block-library/src/social-links/social-link/icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
/**
* WordPress dependencies
*/
import { Path, SVG } from '@wordpress/components';

export default (
<SVG xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><Path fill="none" d="M0 0h24v24H0V0z" /><Path d="M11.99 18.54l-7.37-5.73L3 14.07l9 7 9-7-1.63-1.27zM12 16l7.36-5.73L21 9l-9-7-9 7 1.63 1.27L12 16zm0-11.47L17.74 9 12 13.47 6.26 9 12 4.53z" /></SVG>
);
31 changes: 31 additions & 0 deletions packages/block-library/src/social-links/social-link/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* WordPress dependencies
*/
import { __ } from '@wordpress/i18n';

/**
* Internal dependencies
*/
import edit from './edit';
import icon from './icon';
import metadata from './block.json';
import save from './save';

const { name } = metadata;

export { metadata, name };

export const settings = {
title: __( 'Social links' ),
parent: [ 'core/social-links' ],
icon,
description: __( 'Display a row of icons of your social media accounts.' ),
supports: {
inserter: false,
reusable: false,
html: false,
},
edit,
save,
};

22 changes: 22 additions & 0 deletions packages/block-library/src/social-links/social-link/save.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* External dependencies
*/
import classnames from 'classnames';

/**
* WordPress dependencies
*/
import { InnerBlocks } from '@wordpress/block-editor';

export default function save( { attributes } ) {
const { verticalAlignment, url } = attributes;
const wrapperClasses = classnames( {
[ `is-vertically-aligned-${ verticalAlignment }` ]: verticalAlignment,
} );

return (
<div className={ wrapperClasses }>
<InnerBlocks.Content />
</div>
);
}
16 changes: 16 additions & 0 deletions packages/block-library/src/social-links/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/**
* External dependencies
*/
import memoize from 'memize';
import { times } from 'lodash';

/**
* Returns the layouts configuration for a given number of columns.
*
* @param {number} columns Number of columns.
*
* @return {Object[]} Columns layout configuration.
*/
export const getColumnsTemplate = memoize( ( links ) => {
return times( links, () => [ 'core/social-link' ] );
} );
Loading