diff --git a/blocks/inspector-controls/select-control/index.js b/blocks/inspector-controls/select-control/index.js index 261ac6f789b29..855581238ee9c 100644 --- a/blocks/inspector-controls/select-control/index.js +++ b/blocks/inspector-controls/select-control/index.js @@ -14,16 +14,19 @@ import { withInstanceId } from '@wordpress/components'; import BaseControl from './../base-control'; import './style.scss'; -function SelectControl( { label, selected, help, instanceId, onBlur, options = [], ...props } ) { +function SelectControl( { label, help, instanceId, onChange, options = [], ...props } ) { const id = 'inspector-select-control-' + instanceId; - const onBlurValue = ( event ) => onBlur( event.target.value ); + const onChangeValue = ( event ) => onChange( event.target.value ); + // Disable reason: A select with an onchange throws a warning + + /* eslint-disable jsx-a11y/no-onchange */ return ! isEmpty( options ) && ( ); + /* eslint-enable jsx-a11y/no-onchange */ } export default withInstanceId( SelectControl ); diff --git a/blocks/library/gallery/index.js b/blocks/library/gallery/index.js index 2faaeef761e31..49ca753fbee6b 100644 --- a/blocks/library/gallery/index.js +++ b/blocks/library/gallery/index.js @@ -172,8 +172,8 @@ registerBlockType( 'core/gallery', { /> diff --git a/blocks/library/image/block.js b/blocks/library/image/block.js new file mode 100644 index 0000000000000..e6bd5a8f2ad69 --- /dev/null +++ b/blocks/library/image/block.js @@ -0,0 +1,259 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; +import ResizableBox from 'react-resizable-box'; +import { startCase, findKey } from 'lodash'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Component } from '@wordpress/element'; +import { mediaUpload } from '@wordpress/utils'; +import { Placeholder, Dashicon, Toolbar, DropZone, FormFileUpload } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import withEditorSettings from '../../with-editor-settings'; +import Editable from '../../editable'; +import MediaUploadButton from '../../media-upload-button'; +import InspectorControls from '../../inspector-controls'; +import TextControl from '../../inspector-controls/text-control'; +import SelectControl from '../../inspector-controls/select-control'; +import BlockControls from '../../block-controls'; +import BlockAlignmentToolbar from '../../block-alignment-toolbar'; +import BlockDescription from '../../block-description'; +import UrlInputButton from '../../url-input/button'; +import ImageSize from './image-size'; + +class ImageBlock extends Component { + constructor() { + super( ...arguments ); + this.updateAlt = this.updateAlt.bind( this ); + this.updateAlignment = this.updateAlignment.bind( this ); + this.onSelectImage = this.onSelectImage.bind( this ); + this.onSetHref = this.onSetHref.bind( this ); + this.updateImageSize = this.updateImageSize.bind( this ); + this.state = { + availableSizes: {}, + }; + } + + componentDidMount() { + if ( this.props.attributes.id ) { + this.fetchMedia( this.props.attributes.id ); + } + } + + componentWillUnmout() { + if ( this.fetchImageRequest ) { + this.fetchImageRequest.abort(); + } + } + + onSelectImage( media ) { + this.props.setAttributes( { url: media.url, alt: media.alt, caption: media.caption, id: media.id } ); + this.fetchMedia( media.id ); + } + + onSetHref( value ) { + this.props.setAttributes( { href: value } ); + } + + updateAlt( newAlt ) { + this.props.setAttributes( { alt: newAlt } ); + } + + updateAlignment( nextAlign ) { + const extraUpdatedAttributes = [ 'wide', 'full' ].indexOf( nextAlign ) !== -1 + ? { width: undefined, height: undefined } + : {}; + this.props.setAttributes( { ...extraUpdatedAttributes, align: nextAlign } ); + } + + fetchMedia( id ) { + if ( this.fetchImageRequest ) { + this.fetchImageRequest.abort(); + } + this.fetchImageRequest = new wp.api.models.Media( { id } ).fetch(); + this.fetchImageRequest.then( ( image ) => { + this.setState( { + availableSizes: image.media_details.sizes, + } ); + } ); + } + + updateImageSize( selectedSize ) { + this.props.setAttributes( { + url: this.state.availableSizes[ selectedSize ].source_url, + } ); + } + + render() { + const { attributes, setAttributes, focus, setFocus, className, settings } = this.props; + const { url, alt, caption, align, id, href, width, height } = attributes; + + const availableSizes = Object.keys( this.state.availableSizes ).sort(); + const selectedSize = findKey( this.state.availableSizes, ( size ) => size.source_url === url ); + const isResizable = [ 'wide', 'full' ].indexOf( align ) === -1; + const uploadButtonProps = { isLarge: true }; + const uploadFromFiles = ( event ) => mediaUpload( event.target.files, setAttributes ); + const dropFiles = ( files ) => mediaUpload( files, setAttributes ); + + const controls = ( + focus && ( + + + + +
  • + + + +
  • + +
    +
    + ) + ); + + if ( ! url ) { + return [ + controls, + + + + { __( 'Upload' ) } + + + { __( 'Insert from Media Library' ) } + + , + ]; + } + + const focusCaption = ( focusValue ) => setFocus( { editable: 'caption', ...focusValue } ); + const classes = classnames( className, { + 'is-transient': 0 === url.indexOf( 'blob:' ), + 'is-resized': !! width, + 'is-focused': !! focus, + } ); + + // Disable reason: Each block can be selected by clicking on it + + /* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */ + return [ + controls, + focus && ( + + +

    { __( 'Worth a thousand words.' ) }

    +
    +

    { __( 'Image Settings' ) }

    + + { !! availableSizes.length && ( + ( { + value: imageSize, + label: startCase( imageSize ), + } ) ) } + onChange={ this.updateImageSize } + /> + ) } +
    + ), +
    + + { ( sizes ) => { + const { + imageWidthWithinContainer, + imageHeightWithinContainer, + imageWidth, + imageHeight, + } = sizes; + const currentWidth = width || imageWidthWithinContainer; + const currentHeight = height || imageHeightWithinContainer; + const img = {; + if ( ! isResizable || ! imageWidthWithinContainer ) { + return img; + } + const ratio = imageWidth / imageHeight; + const minWidth = imageWidth < imageHeight ? 10 : 10 * ratio; + const minHeight = imageHeight < imageWidth ? 10 : 10 / ratio; + return ( + { + setAttributes( { + width: elt.clientWidth, + height: elt.clientHeight, + } ); + } } + > + { img } + + ); + } } + + { ( caption && caption.length > 0 ) || !! focus ? ( + setAttributes( { caption: value } ) } + inlineToolbar + /> + ) : null } +
    , + ]; + /* eslint-enable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */ + } +} + +export default withEditorSettings()( ImageBlock ); diff --git a/blocks/library/image/index.js b/blocks/library/image/index.js index 2097dd3f859ff..c2024e08b1963 100644 --- a/blocks/library/image/index.js +++ b/blocks/library/image/index.js @@ -1,15 +1,7 @@ -/** - * External dependencies - */ -import classnames from 'classnames'; -import ResizableBox from 'react-resizable-box'; - /** * WordPress dependencies */ import { __ } from '@wordpress/i18n'; -import { mediaUpload } from '@wordpress/utils'; -import { Placeholder, Dashicon, Toolbar, DropZone, FormFileUpload } from '@wordpress/components'; /** * Internal dependencies @@ -17,16 +9,7 @@ import { Placeholder, Dashicon, Toolbar, DropZone, FormFileUpload } from '@wordp import './style.scss'; import './editor.scss'; import { registerBlockType, source } from '../../api'; -import withEditorSettings from '../../with-editor-settings'; -import Editable from '../../editable'; -import MediaUploadButton from '../../media-upload-button'; -import InspectorControls from '../../inspector-controls'; -import TextControl from '../../inspector-controls/text-control'; -import BlockControls from '../../block-controls'; -import BlockAlignmentToolbar from '../../block-alignment-toolbar'; -import BlockDescription from '../../block-description'; -import UrlInputButton from '../../url-input/button'; -import ImageSize from './image-size'; +import ImageBlock from './block'; const { attr, children } = source; @@ -89,165 +72,7 @@ registerBlockType( 'core/image', { } }, - edit: withEditorSettings()( ( { attributes, setAttributes, focus, setFocus, className, settings } ) => { - const { url, alt, caption, align, id, href, width, height } = attributes; - const updateAlt = ( newAlt ) => setAttributes( { alt: newAlt } ); - const updateAlignment = ( nextAlign ) => { - const extraUpdatedAttributes = [ 'wide', 'full' ].indexOf( nextAlign ) !== -1 - ? { width: undefined, height: undefined } - : {}; - setAttributes( { ...extraUpdatedAttributes, align: nextAlign } ); - }; - const onSelectImage = ( media ) => { - setAttributes( { url: media.url, alt: media.alt, caption: media.caption, id: media.id } ); - }; - const isResizable = [ 'wide', 'full' ].indexOf( align ) === -1; - const uploadButtonProps = { isLarge: true }; - const onSetHref = ( value ) => setAttributes( { href: value } ); - const uploadFromFiles = ( event ) => mediaUpload( event.target.files, setAttributes ); - const dropFiles = ( files ) => mediaUpload( files, setAttributes ); - - const controls = ( - focus && ( - - - - -
  • - - - -
  • - -
    -
    - ) - ); - - if ( ! url ) { - return [ - controls, - - - - { __( 'Upload' ) } - - - { __( 'Insert from Media Library' ) } - - , - ]; - } - - const focusCaption = ( focusValue ) => setFocus( { editable: 'caption', ...focusValue } ); - const classes = classnames( className, { - 'is-transient': 0 === url.indexOf( 'blob:' ), - 'is-resized': !! width, - 'is-focused': !! focus, - } ); - - // Disable reason: Each block can be selected by clicking on it - - /* eslint-disable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */ - return [ - controls, - focus && ( - - -

    { __( 'Worth a thousand words.' ) }

    -
    -

    { __( 'Image Settings' ) }

    - -
    - ), -
    - - { ( sizes ) => { - const { - imageWidthWithinContainer, - imageHeightWithinContainer, - imageWidth, - imageHeight, - } = sizes; - const currentWidth = width || imageWidthWithinContainer; - const currentHeight = height || imageHeightWithinContainer; - const img = {; - if ( ! isResizable || ! imageWidthWithinContainer ) { - return img; - } - const ratio = imageWidth / imageHeight; - const minWidth = imageWidth < imageHeight ? 10 : 10 * ratio; - const minHeight = imageHeight < imageWidth ? 10 : 10 / ratio; - return ( - { - setAttributes( { - width: elt.clientWidth, - height: elt.clientHeight, - } ); - } } - > - { img } - - ); - } } - - { ( caption && caption.length > 0 ) || !! focus ? ( - setAttributes( { caption: value } ) } - inlineToolbar - /> - ) : null } -
    , - ]; - /* eslint-enable jsx-a11y/no-static-element-interactions, jsx-a11y/onclick-has-role, jsx-a11y/click-events-have-key-events */ - } ), + edit: ImageBlock, save( { attributes } ) { const { url, alt, caption, align, href, width, height } = attributes;