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

Create a Book block #134

Merged
merged 4 commits into from
Aug 21, 2020
Merged
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
27 changes: 27 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# This file is for unifying the coding style for different editors and IDEs
# editorconfig.org

# WordPress Coding Standards
# https://make.wordpress.org/core/handbook/coding-standards/

root = true

[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = tab

[*.yml]
indent_style = space
indent_size = 2

[*.md]
trim_trailing_whitespace = false

[*.{gradle,java,kt}]
indent_style = space

[packages/react-native-*/**.xml]
indent_style = space
4 changes: 4 additions & 0 deletions .wp-env.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"core": "WordPress/WordPress#master",
"plugins": [ "." ]
}
61 changes: 61 additions & 0 deletions blocks/book/editor.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/**
* The following styles get applied inside the editor only.
*
* Replace them with your own styles or remove the file completely.
*/

// This selector should be revisited if/when we can leverage lightBlockWrapper.
.wp-block-a8c-book {
.wp-block-a8c-book__cover {
// Ensure the correct aspect ratio of the cover image, even when the source image is way too big.
height: 100% !important; // Needs high specificity to override an inline style. Would be nice if this could be output by the component itself instead.

// Make the placeholder look like a book.
.components-placeholder {
box-shadow: none;
height: 100%;
}
}

.wp-block-a8c-book__cover-placeholder {
// Default to 33% width.
min-width: 140px;
min-height: 230px;
width: 33% !important;
padding-top: 50%;

.components-placeholder {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
}

// Hide the resize handles on the placeholder.
.components-resizable-box__handle {
display: none;
}
}
}

.wp-block[data-align='center'] > .wp-block-a8c-book {
display: flex;
flex-direction: column;
align-items: center;
}
.wp-block[data-align='left'] > .wp-block-a8c-book {
margin-right: 1em;
}

.wp-block[data-align='right'] > .wp-block-a8c-book {
margin-left: 1em;
}

.wp-block[data-align='left'],
.wp-block[data-align='right'] {
> .wp-block-a8c-book {
margin-top: 0;
margin-bottom: 0;
}
}
9 changes: 9 additions & 0 deletions blocks/book/index.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php

add_action( 'init', function() {
register_block_type( 'a8c/book', [
'editor_script' => 'wpcom-blocks',
'style' => 'wpcom-blocks',
'editor_style' => 'wpcom-blocks-editor',
] );
} );
207 changes: 207 additions & 0 deletions blocks/book/src/edit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,207 @@
import {
BlockControls,
MediaPlaceholder,
MediaUpload,
RichText,
__experimentalBlock as Block,
} from '@wordpress/block-editor';
import { Button, ResizableBox, Toolbar } from '@wordpress/components';
/**
* Retrieves the translation of text.
*
* @see https://developer.wordpress.org/block-editor/packages/packages-i18n/
*/
import { __ } from '@wordpress/i18n';
import { isEmpty } from 'lodash';

import classnames from 'classnames';
import prefixClasses from './prefixClasses';

/**
* The edit function describes the structure of your block in the context of the
* editor. This represents what the editor will render when the block is used.
*
* @see https://developer.wordpress.org/block-editor/developers/block-api/block-edit-save/#edit
*
* @param {Object} [props] Properties passed from the editor.
* @param {string} [props.className] Class name generated for the block.
*
* @return {WPElement} Element to render.
*/

export default function Edit( {
className,
isSelected,
setAttributes,
attributes,
} ) {
const {
author,
align,
height,
imageId,
imageUrl,
publicationDate,
publisher,
title,
width,
} = attributes;
const hasMedia = !! imageId;

const handleResize = ( event, direction, elt, delta ) =>
setAttributes( {
height: parseInt( height + delta.height, 10 ),
width: parseInt( width + delta.width, 10 ),
} );

const handleSelectCoverImage = ( media ) =>
setAttributes( { imageId: media.id, imageUrl: media.url } );

const handleImageLoad = ( event ) => {
const { currentTarget } = event;
const { naturalHeight, naturalWidth } = currentTarget;

setAttributes( { height: naturalHeight, width: naturalWidth } );
};

const classes = classnames( 'wp-block-a8c-book', className );

/**
* Function that creates an event handler for the RichText element,
* which will update the given `attribute`.
*
* @param {String} attribute
*/
const updateAttribute = ( attribute ) => ( value ) =>
setAttributes( { [ attribute ]: value } );

const enabledHandles = {
top: false,
right: align === 'left' || ! align || align === 'center',
left: align === 'right' || align === 'center',
bottom: true,
topRight: false,
bottomRight: false,
bottomLeft: false,
topLeft: false,
};

const resizableBoxClasses = classnames( prefixClasses( '__cover' ), {
[ `${ prefixClasses( '__cover-placeholder' ) }` ]: ! hasMedia,
} );

const shouldDisplayField = ( field ) =>
! RichText.isEmpty( field ) || isSelected;
const shouldDisplayMetadata =
title || author || publisher || publicationDate || isSelected;

return (
<Block.div className={ classes }>
{ hasMedia && (
<BlockControls>
<Toolbar>
<MediaUpload
onSelect={ handleSelectCoverImage }
allowedTypes={ [ 'image' ] }
value={ imageId }
render={ ( { open } ) => (
<Button
className="components-toolbar__control"
onClick={ open }
>
{ __( 'Replace' ) }
</Button>
) }
/>
</Toolbar>
</BlockControls>
) }
<ResizableBox
enable={ enabledHandles }
className={ resizableBoxClasses }
size={ {
height,
width,
} }
defaultSize={ { width: '100%' } }
maxWidth="100%"
onResizeStop={ handleResize }
showHandle={ isSelected }
lockAspectRatio
>
{ hasMedia ? (
<img
src={ imageUrl }
alt={ title }
onLoad={ handleImageLoad }
/>
) : (
<MediaPlaceholder
allowedTypes={ [ 'image' ] }
onSelect={ handleSelectCoverImage }
labels={ {
title: __( 'Book cover image' ),
instructions: __(
"Upload the book's cover image."
),
} }
value={ { id: imageId } }
/>
) }
</ResizableBox>

{ shouldDisplayMetadata && (
<section
className={ prefixClasses( '__meta' ) }
style={ { width } }
>
{ shouldDisplayField( title ) && (
<RichText
keepPlaceholderOnFocus
name="title"
tagName="p"
value={ title }
placeholder="Book title"
className={ prefixClasses( '__title' ) }
onChange={ updateAttribute( 'title' ) }
/>
) }
{ shouldDisplayField( author ) && (
<RichText
keepPlaceholderOnFocus
name="author"
tagName="p"
value={ author }
placeholder="Author name"
onChange={ updateAttribute( 'author' ) }
/>
) }
<p className={ prefixClasses( '__publication' ) }>
{ shouldDisplayField( publisher ) && (
<RichText
keepPlaceholderOnFocus
name="publisher"
tagName="span"
value={ publisher }
placeholder="Publisher"
onChange={ updateAttribute( 'publisher' ) }
/>
) }
{ shouldDisplayField( publicationDate ) && (
<RichText
keepPlaceholderOnFocus
name="publicationDate"
tagName="span"
value={ publicationDate }
placeholder="Publication date"
onChange={ updateAttribute(
'publicationDate'
) }
/>
) }
</p>
</section>
) }
</Block.div>
);
}
14 changes: 14 additions & 0 deletions blocks/book/src/icon.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* WordPress depedencies
*/

import { Path, SVG } from '@wordpress/components';

export const BookIcon = () => (
<SVG xmlns="http://www.w3.org/2000/svg"
width="24" height="24"
viewBox="0 0 24 24"
>
<Path d="M5 5v14c0 1.1.9 2 2 2h10V3H7c-1.1 0-2 .9-2 2zm7 2.5l2 2.5V4.5h1.5v15H7c-.3 0-.5-.2-.5-.5V5c0-.3.2-.5.5-.5h3V10l2-2.5zM18.5 3v18H20V3h-1.5z" />
</SVG>
);
Loading