From 1478e886f42e73294fd254d26868eb3fe36516c0 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Wed, 21 Aug 2019 17:05:44 -0400 Subject: [PATCH 1/7] Add ImageSizeControl --- .../components/image-size-control/index.js | 125 ++++++++++++++++++ .../components/image-size-control/style.scss | 26 ++++ packages/block-editor/src/components/index.js | 1 + packages/block-editor/src/style.scss | 1 + 4 files changed, 153 insertions(+) create mode 100644 packages/block-editor/src/components/image-size-control/index.js create mode 100644 packages/block-editor/src/components/image-size-control/style.scss diff --git a/packages/block-editor/src/components/image-size-control/index.js b/packages/block-editor/src/components/image-size-control/index.js new file mode 100644 index 00000000000000..92c7e12700d60d --- /dev/null +++ b/packages/block-editor/src/components/image-size-control/index.js @@ -0,0 +1,125 @@ +/** + * External dependencies + */ +import { isEmpty } from 'lodash'; + +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; +import { Button, ButtonGroup, SelectControl, TextControl } from '@wordpress/components'; +import { Component } from '@wordpress/element'; + +class ImageSizeControl extends Component { + /** + * Run additional operations during component initialization. + * + * @param {Object} props + */ + constructor( props ) { + super( props ); + + this.updateImage = this.updateImage.bind( this ); + this.updateWidth = this.updateWidth.bind( this ); + this.updateHeight = this.updateHeight.bind( this ); + this.updateDimensions = this.updateDimensions.bind( this ); + } + + updateImage( slug ) { + this.props.onChangeImage( slug ); + } + + updateWidth( width ) { + this.props.onChange( { width: parseInt( width, 10 ) } ); + } + + updateHeight( height ) { + this.props.onChange( { height: parseInt( height, 10 ) } ); + } + + updateDimensions( width = undefined, height = undefined ) { + return () => { + this.props.onChange( { width, height } ); + }; + } + + render() { + const { + imageWidth, + imageHeight, + imageSizeOptions, + isResizable = true, + slug, + width, + height, + } = this.props; + + return ( + <> + { ! isEmpty( imageSizeOptions ) && ( + + ) } + { isResizable && ( +
+

+ { __( 'Image Dimensions' ) } +

+
+ + +
+
+ + { [ 25, 50, 75, 100 ].map( ( scale ) => { + const scaledWidth = Math.round( imageWidth * ( scale / 100 ) ); + const scaledHeight = Math.round( imageHeight * ( scale / 100 ) ); + + const isCurrent = width === scaledWidth && height === scaledHeight; + + return ( + + ); + } ) } + + +
+
+ ) } + + ); + } +} + +export default ImageSizeControl; diff --git a/packages/block-editor/src/components/image-size-control/style.scss b/packages/block-editor/src/components/image-size-control/style.scss new file mode 100644 index 00000000000000..2a0bf9fa6c3513 --- /dev/null +++ b/packages/block-editor/src/components/image-size-control/style.scss @@ -0,0 +1,26 @@ +.block-editor-image-size-control { + margin-bottom: 1em; + + .block-editor-image-size-control__row { + display: flex; + justify-content: space-between; + + .block-editor-image-size-control__width, + .block-editor-image-size-control__height { + margin-bottom: 0.5em; + + // Fix the text and placeholder text being misaligned in Safari + input { + line-height: 1.25; + } + } + + .block-editor-image-size-control__width { + margin-right: 5px; + } + + .block-editor-image-size-control__height { + margin-left: 5px; + } + } +} diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index 3a5bc7692f6408..e607cca38970e5 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -5,6 +5,7 @@ export * from './colors'; export * from './gradients'; export * from './font-sizes'; +export { default as __experimentalImageSizeControl } from './image-size-control'; export { default as AlignmentToolbar } from './alignment-toolbar'; export { default as Autocomplete } from './autocomplete'; export { default as BlockAlignmentToolbar } from './block-alignment-toolbar'; diff --git a/packages/block-editor/src/style.scss b/packages/block-editor/src/style.scss index 079002c74a5452..0ccc3c0a3df14b 100644 --- a/packages/block-editor/src/style.scss +++ b/packages/block-editor/src/style.scss @@ -21,6 +21,7 @@ @import "./components/contrast-checker/style.scss"; @import "./components/default-block-appender/style.scss"; @import "./components/link-control/style.scss"; +@import "./components/image-size-control/style.scss"; @import "./components/inner-blocks/style.scss"; @import "./components/inserter/style.scss"; @import "./components/inserter-list-item/style.scss"; From 6679041ec7276312b85b879d352dc8bd25cbf040 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Thu, 22 Aug 2019 13:37:33 -0400 Subject: [PATCH 2/7] Remove helper functions, use callbacks directly --- .../components/image-size-control/index.js | 23 ++++--------------- 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/packages/block-editor/src/components/image-size-control/index.js b/packages/block-editor/src/components/image-size-control/index.js index 92c7e12700d60d..6d6d06219802b3 100644 --- a/packages/block-editor/src/components/image-size-control/index.js +++ b/packages/block-editor/src/components/image-size-control/index.js @@ -19,24 +19,9 @@ class ImageSizeControl extends Component { constructor( props ) { super( props ); - this.updateImage = this.updateImage.bind( this ); - this.updateWidth = this.updateWidth.bind( this ); - this.updateHeight = this.updateHeight.bind( this ); this.updateDimensions = this.updateDimensions.bind( this ); } - updateImage( slug ) { - this.props.onChangeImage( slug ); - } - - updateWidth( width ) { - this.props.onChange( { width: parseInt( width, 10 ) } ); - } - - updateHeight( height ) { - this.props.onChange( { height: parseInt( height, 10 ) } ); - } - updateDimensions( width = undefined, height = undefined ) { return () => { this.props.onChange( { width, height } ); @@ -52,6 +37,8 @@ class ImageSizeControl extends Component { slug, width, height, + onChange, + onChangeImage, } = this.props; return ( @@ -61,7 +48,7 @@ class ImageSizeControl extends Component { label={ __( 'Image Size' ) } value={ slug } options={ imageSizeOptions } - onChange={ this.updateImage } + onChange={ onChangeImage } /> ) } { isResizable && ( @@ -76,7 +63,7 @@ class ImageSizeControl extends Component { label={ __( 'Width' ) } value={ width || imageWidth || '' } min={ 1 } - onChange={ this.updateWidth } + onChange={ ( value ) => onChange( { width: parseInt( value, 10 ) } ) } /> onChange( { height: parseInt( value, 10 ) } ) } />
From 1a435f258bac650f00c6c69f860843afadc11dac Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Thu, 22 Aug 2019 13:38:48 -0400 Subject: [PATCH 3/7] Make imageSizeOptions an optional prop If this isn't passed through, we don't show the dropdown --- .../block-editor/src/components/image-size-control/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/block-editor/src/components/image-size-control/index.js b/packages/block-editor/src/components/image-size-control/index.js index 6d6d06219802b3..662e081c19b483 100644 --- a/packages/block-editor/src/components/image-size-control/index.js +++ b/packages/block-editor/src/components/image-size-control/index.js @@ -32,7 +32,7 @@ class ImageSizeControl extends Component { const { imageWidth, imageHeight, - imageSizeOptions, + imageSizeOptions = [], isResizable = true, slug, width, From 2500c90106c4bdbc6685401394e382c235f251db Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Thu, 22 Aug 2019 12:58:00 -0400 Subject: [PATCH 4/7] Use new ImageSizeControl for the image block --- packages/block-library/src/image/edit.js | 94 +++--------------------- 1 file changed, 12 insertions(+), 82 deletions(-) diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index 63771eac15ce76..b86b392cd31098 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -4,7 +4,6 @@ import classnames from 'classnames'; import { get, - isEmpty, filter, map, last, @@ -17,12 +16,9 @@ import { */ import { getBlobByURL, isBlobURL, revokeBlobURL } from '@wordpress/blob'; import { - Button, - ButtonGroup, ExternalLink, PanelBody, ResizableBox, - SelectControl, Spinner, TextareaControl, TextControl, @@ -35,6 +31,7 @@ import { BlockAlignmentToolbar, BlockControls, BlockIcon, + ImageSizeControl, InspectorControls, InspectorAdvancedControls, MediaPlaceholder, @@ -104,9 +101,6 @@ export class ImageEdit extends Component { this.onSelectImage = this.onSelectImage.bind( this ); this.onSelectURL = this.onSelectURL.bind( this ); this.updateImage = this.updateImage.bind( this ); - this.updateWidth = this.updateWidth.bind( this ); - this.updateHeight = this.updateHeight.bind( this ); - this.updateDimensions = this.updateDimensions.bind( this ); this.onSetHref = this.onSetHref.bind( this ); this.onSetTitle = this.onSetTitle.bind( this ); this.getFilename = this.getFilename.bind( this ); @@ -297,20 +291,6 @@ export class ImageEdit extends Component { } ); } - updateWidth( width ) { - this.props.setAttributes( { width: parseInt( width, 10 ) } ); - } - - updateHeight( height ) { - this.props.setAttributes( { height: parseInt( height, 10 ) } ); - } - - updateDimensions( width = undefined, height = undefined ) { - return () => { - this.props.setAttributes( { width, height } ); - }; - } - getFilename( url ) { const path = getPath( url ); if ( path ) { @@ -451,67 +431,17 @@ export class ImageEdit extends Component { } /> - { ! isEmpty( imageSizeOptions ) && ( - - ) } - { isResizable && ( -
-

- { __( 'Image Dimensions' ) } -

-
- - -
-
- - { [ 25, 50, 75, 100 ].map( ( scale ) => { - const scaledWidth = Math.round( imageWidth * ( scale / 100 ) ); - const scaledHeight = Math.round( imageHeight * ( scale / 100 ) ); - - const isCurrent = width === scaledWidth && height === scaledHeight; - - return ( - - ); - } ) } - - -
-
- ) } + setAttributes( value ) } + slug={ sizeSlug } + width={ width } + height={ height } + imageSizeOptions={ imageSizeOptions } + isResizable={ isResizable } + imageWidth={ imageWidth } + imageHeight={ imageHeight } + /> From 9fbc751abc275d8edd8133b7fb8d28bcb29401e6 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Thu, 22 Aug 2019 13:59:29 -0400 Subject: [PATCH 5/7] Remove unused CSS --- packages/block-library/src/image/editor.scss | 27 -------------------- 1 file changed, 27 deletions(-) diff --git a/packages/block-library/src/image/editor.scss b/packages/block-library/src/image/editor.scss index 1f66521f7e32d3..561141334ad87a 100644 --- a/packages/block-library/src/image/editor.scss +++ b/packages/block-library/src/image/editor.scss @@ -52,33 +52,6 @@ } } -.edit-post-sidebar .block-library-image__dimensions { - margin-bottom: 1em; - - .block-library-image__dimensions__row { - display: flex; - justify-content: space-between; - - .block-library-image__dimensions__width, - .block-library-image__dimensions__height { - margin-bottom: 0.5em; - - // Fix the text and placeholder text being misaligned in Safari - input { - line-height: 1.25; - } - } - - .block-library-image__dimensions__width { - margin-right: 5px; - } - - .block-library-image__dimensions__height { - margin-left: 5px; - } - } -} - .block-editor-block-list__block[data-type="core/image"] .block-editor-block-toolbar .block-editor-url-input__button-modal { position: absolute; left: 0; From 400ccdc65169e39efcefb991b9c8050d223a1b41 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Thu, 22 Aug 2019 15:29:32 -0400 Subject: [PATCH 6/7] Add README --- .../components/image-size-control/README.md | 108 ++++++++++++++++++ .../components/image-size-control/index.js | 6 +- 2 files changed, 111 insertions(+), 3 deletions(-) create mode 100644 packages/block-editor/src/components/image-size-control/README.md diff --git a/packages/block-editor/src/components/image-size-control/README.md b/packages/block-editor/src/components/image-size-control/README.md new file mode 100644 index 00000000000000..21eb3cfa1823fb --- /dev/null +++ b/packages/block-editor/src/components/image-size-control/README.md @@ -0,0 +1,108 @@ +# ImageSizeControl + +Allow users to control the width & height of an image. + +## Usage + +Render a ImageSizeControl. + +```jsx +import { ImageSizeControl } from '@wordpress/components'; +import { withState } from '@wordpress/compose'; + +const MyImageSizeControl = withState( { + width: null, + height: null, +} )( ( { width, height, setState } ) => { + // In this example, we have one image with a fixed size of 600x600. + const imageWidth = 600; + const imageHeight = 600; + + return ( + setState( value ) } + width={ width } + height={ height } + imageWidth={ imageWidth } + imageHeight={ imageHeight } + /> + ); +} ); +``` + +## Props + +The component accepts the following props: + +### slug + +The currently-selected image size slug (`thumbnail`, `large`, etc). This is used by the parent component to get the specific image, which is used to populate `imageHeight` & `imageWidth`. This is not required, but necessary when `imageSizeOptions` is used. + +- Type: `string` +- Required: No + +### height + +The height of the image when displayed. + +- Type: `number` +- Required: No + +### width + +The width of the image when displayed. + +- Type: `number` +- Required: No + +### onChange + +The function called when the image size changes. It is passed an object with `{ width, height }` (potentially just one if only one dimension changed). + +- Type: `Function` +- Required: Yes + +### onChangeImage + +The function called when a new image size is selected. It is passed the `slug` as an argument. This is not required, but necessary when `imageSizeOptions` is used. + +- Type: `Function` +- Required: No + +### imageSizeOptions + +An array of image size slugs and labels. Should be of the format: + +```js +[ + { value: 'thumbnail', label: 'Thumbnail' }, + { value: 'medium', label: 'Medium' }, + ... +] +``` + +If not provided, the "Image Size" dropdown is not displayed. + +- Type: `array` +- Required: No + +### isResizable + +A boolean control for showing the resize fields "Image Dimensions". Set this to false if you want images to always be the fixed size of the selected image. + +- Type: `boolean` +- Required: No + +### imageWidth + +The width of the currently selected image, used for calculating the percentage sizes. This will likely be updated when the image size slug changes, but does not control the image display (that's the `width` prop). + +- Type: `number` +- Required: Yes + +### imageHeight + +The height of the currently selected image, used for calculating the percentage sizes. This will likely be updated when the image size slug changes, but does not control the image display (that's the `height` prop). + +- Type: `number` +- Required: Yes diff --git a/packages/block-editor/src/components/image-size-control/index.js b/packages/block-editor/src/components/image-size-control/index.js index 662e081c19b483..01e5251959bb82 100644 --- a/packages/block-editor/src/components/image-size-control/index.js +++ b/packages/block-editor/src/components/image-size-control/index.js @@ -1,7 +1,7 @@ /** * External dependencies */ -import { isEmpty } from 'lodash'; +import { isEmpty, noop } from 'lodash'; /** * WordPress dependencies @@ -38,7 +38,7 @@ class ImageSizeControl extends Component { width, height, onChange, - onChangeImage, + onChangeImage = noop, } = this.props; return ( @@ -97,7 +97,7 @@ class ImageSizeControl extends Component { From fbb187c106c394dad61e52990d65112052263668 Mon Sep 17 00:00:00 2001 From: Kelly Dwan Date: Sun, 29 Dec 2019 13:06:14 -0500 Subject: [PATCH 7/7] Fix rebase issues --- .../block-editor/src/components/image-size-control/index.js | 2 +- packages/block-editor/src/components/index.js | 2 +- packages/block-library/src/image/edit.js | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/block-editor/src/components/image-size-control/index.js b/packages/block-editor/src/components/image-size-control/index.js index 01e5251959bb82..f77227e650eb12 100644 --- a/packages/block-editor/src/components/image-size-control/index.js +++ b/packages/block-editor/src/components/image-size-control/index.js @@ -87,7 +87,7 @@ class ImageSizeControl extends Component { key={ scale } isSmall isPrimary={ isCurrent } - aria-pressed={ isCurrent } + isPressed={ isCurrent } onClick={ this.updateDimensions( scaledWidth, scaledHeight ) } > { scale }% diff --git a/packages/block-editor/src/components/index.js b/packages/block-editor/src/components/index.js index e607cca38970e5..48e8559d7990b9 100644 --- a/packages/block-editor/src/components/index.js +++ b/packages/block-editor/src/components/index.js @@ -5,7 +5,6 @@ export * from './colors'; export * from './gradients'; export * from './font-sizes'; -export { default as __experimentalImageSizeControl } from './image-size-control'; export { default as AlignmentToolbar } from './alignment-toolbar'; export { default as Autocomplete } from './autocomplete'; export { default as BlockAlignmentToolbar } from './block-alignment-toolbar'; @@ -27,6 +26,7 @@ export { default as __experimentalGradientPickerControl } from './gradient-picke export { default as __experimentalGradientPickerPanel } from './gradient-picker/panel'; export { default as __experimentalColorGradientControl } from './colors-gradients/control'; export { default as __experimentalPanelColorGradientSettings } from './colors-gradients/panel-color-gradient-settings'; +export { default as __experimentalImageSizeControl } from './image-size-control'; export { default as InnerBlocks } from './inner-blocks'; export { default as InspectorAdvancedControls } from './inspector-advanced-controls'; export { default as InspectorControls } from './inspector-controls'; diff --git a/packages/block-library/src/image/edit.js b/packages/block-library/src/image/edit.js index b86b392cd31098..ae24d7712759d5 100644 --- a/packages/block-library/src/image/edit.js +++ b/packages/block-library/src/image/edit.js @@ -31,12 +31,12 @@ import { BlockAlignmentToolbar, BlockControls, BlockIcon, - ImageSizeControl, InspectorControls, InspectorAdvancedControls, MediaPlaceholder, MediaReplaceFlow, RichText, + __experimentalImageSizeControl as ImageSizeControl, __experimentalImageURLInputUI as ImageURLInputUI, } from '@wordpress/block-editor'; import {