From 16eb7f544fa9ae3b05d1fa3c3ea22a8da4e5e4c1 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 18 Feb 2019 14:04:07 +0100 Subject: [PATCH 01/29] Implement image filters for tiled gallery block --- .../extensions/tiled-gallery/css-gram.scss | 86 +++++++++++ .../extensions/tiled-gallery/edit.jsx | 57 ++++--- .../extensions/tiled-gallery/editor.scss | 27 ++++ .../tiled-gallery/filter-toolbar.js | 140 ++++++++++++++++++ .../tiled-gallery/gallery-image/edit.js | 2 + .../tiled-gallery/gallery-image/save.js | 8 +- .../extensions/tiled-gallery/index.js | 3 + .../extensions/tiled-gallery/layout/index.js | 4 +- .../extensions/tiled-gallery/save.jsx | 3 +- .../extensions/tiled-gallery/view.scss | 21 +++ 10 files changed, 330 insertions(+), 21 deletions(-) create mode 100644 client/gutenberg/extensions/tiled-gallery/css-gram.scss create mode 100644 client/gutenberg/extensions/tiled-gallery/filter-toolbar.js diff --git a/client/gutenberg/extensions/tiled-gallery/css-gram.scss b/client/gutenberg/extensions/tiled-gallery/css-gram.scss new file mode 100644 index 0000000000000..9fd2f49c52aa1 --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/css-gram.scss @@ -0,0 +1,86 @@ +/** + * This code is based on CSS gram: + * https://github.com/una/CSSgram/tree/master + * + * Due to the packaging options available, the source has been duplicated and adapted here + * to best fit our specific needs. + */ + +/* From https://github.com/una/CSSgram/blob/0.1.12/source/scss/_shared.scss */ +@mixin pseudo-elem { + content: ''; + display: block; + height: 100%; + width: 100%; + top: 0; + left: 0; + position: absolute; + pointer-events: none; +} + +@mixin filter-base { + position: relative; + + img { + width: 100%; + z-index: 1; + } + + &::before { + @include pseudo-elem; + z-index: 2; + } + + &::after { + @include pseudo-elem; + z-index: 3; + } +} + +/** + * 1977 + * From https://github.com/una/CSSgram/blob/0.1.12/source/scss/1977.scss + */ +@mixin _1977( $filters... ) { + @include filter-base; + filter: contrast( 1.1 ) brightness( 1.1 ) saturate( 1.3 ) $filters; + + &::after { + background: rgba( 243, 106, 188, 0.3 ); + mix-blend-mode: screen; + } + + @content; +} + +/* + * Clarendon + * From https://github.com/una/CSSgram/blob/0.1.12/source/scss/clarendon.scss + */ +@mixin clarendon( $filters... ) { + @include filter-base; + filter: contrast( 1.2 ) saturate( 1.35 ) $filters; + + &::before { + background: rgba( 127, 187, 227, 0.2 ); + mix-blend-mode: overlay; + } + + @content; +} + +/** + * Gingham + * From https://github.com/una/CSSgram/blob/0.1.12/source/scss/gingham.scss + */ +@mixin gingham( $filters... ) { + @include filter-base; + filter: brightness( 1.05 ) hue-rotate( -10deg ) $filters; + + &::after { + background: rgb( 230, 230, 250 ); + mix-blend-mode: soft-light; + } + + @content; +} diff --git a/client/gutenberg/extensions/tiled-gallery/edit.jsx b/client/gutenberg/extensions/tiled-gallery/edit.jsx index 1d8c0aec8ecc9..3e864a62897aa 100644 --- a/client/gutenberg/extensions/tiled-gallery/edit.jsx +++ b/client/gutenberg/extensions/tiled-gallery/edit.jsx @@ -24,6 +24,7 @@ import { /** * Internal dependencies */ +import FilterToolbar from './filter-toolbar'; import Layout from './layout'; import { __ } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; import { ALLOWED_MEDIA_TYPES, LAYOUT_STYLES, MAX_COLUMNS } from './constants'; @@ -155,31 +156,50 @@ class TiledGalleryEdit extends Component { render() { const { selectedImage } = this.state; - const { attributes, isSelected, className, noticeOperations, noticeUI } = this.props; - const { align, columns = defaultColumnsNumber( attributes ), images, linkTo } = attributes; + const { + attributes, + isSelected, + className, + noticeOperations, + noticeUI, + setAttributes, + } = this.props; + const { + align, + columns = defaultColumnsNumber( attributes ), + imageFilter, + images, + linkTo, + } = attributes; const dropZone = ; const controls = ( { !! images.length && ( - - img.id ) } - render={ ( { open } ) => ( - - ) } + + + img.id ) } + render={ ( { open } ) => ( + + ) } + /> + + setAttributes( { imageFilter: value } ) } /> - + ) } ); @@ -237,6 +257,7 @@ class TiledGalleryEdit extends Component { align={ align } className={ className } columns={ columns } + imageFilter={ imageFilter } images={ images } layoutStyle={ layoutStyle } linkTo={ linkTo } diff --git a/client/gutenberg/extensions/tiled-gallery/editor.scss b/client/gutenberg/extensions/tiled-gallery/editor.scss index 0414f09bf14b6..919b1bda02619 100644 --- a/client/gutenberg/extensions/tiled-gallery/editor.scss +++ b/client/gutenberg/extensions/tiled-gallery/editor.scss @@ -32,6 +32,13 @@ &.is-selected { outline: 4px solid $tiled-gallery-selection; + + // Disable filters when selected + filter: none; + &::before, + &::after { + content: none; + } } &.is-transient img { @@ -154,3 +161,23 @@ width: 20px; } } + +.tiled-gallery__filter-picker-menu { + $active-item-outline-width: 2px; + + // @TODO replace with Gutenberg variables + $dark-gray-500: #555d66; + $dark-gray-900: #191e23; + + padding: 7px; + + // Leave space between elements for active state styling + .components-menu-item__button + .components-menu-item__button { + margin-top: $active-item-outline-width; + } + + .components-menu-item__button.is-active { + color: $dark-gray-900; + box-shadow: 0 0 0 $active-item-outline-width $dark-gray-500 !important; + } +} diff --git a/client/gutenberg/extensions/tiled-gallery/filter-toolbar.js b/client/gutenberg/extensions/tiled-gallery/filter-toolbar.js new file mode 100644 index 0000000000000..1782c5e0001a2 --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/filter-toolbar.js @@ -0,0 +1,140 @@ +/** + * External Dependencies + */ +import { Dropdown, MenuItem, NavigableMenu, Path, SVG, Toolbar } from '@wordpress/components'; + +/** + * Internal dependencies + */ +import { __, _x } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; + +const availableFilters = [ + { + icon: ( + /* Custom icon */ + + + + + ), + title: _x( 'Original', 'image style' ), + value: undefined, + }, + { + icon: ( + /* Material Black and White icon */ + + + + + ), + title: _x( 'Black and White', 'image style' ), + value: 'black-and-white', + }, + { + icon: ( + /* Material Vintage icon */ + + + + + ), + title: _x( 'Sepia', 'image style' ), + value: 'sepia', + }, + { + icon: ( + /* Custom icon */ + + + + + ), + title: '1977', + value: '1977', + }, + { + icon: ( + /* Material Tonality icon */ + + + + + ), + title: _x( 'Clarendon', 'image style' ), + value: 'clarendon', + }, + { + icon: ( + /* Material Drama icon */ + + + + + ), + title: _x( 'Gingham', 'image style' ), + value: 'gingham', + }, +]; + +const label = __( 'Pick an image filter' ); + +export default function FilterToolbar( { value, onChange } ) { + return ( + { + return ( + + + + + ), + }, + ] } + /> + ); + } } + renderContent={ ( { onClose } ) => { + const applyOrUnset = nextValue => () => { + onChange( value === nextValue ? undefined : nextValue ); + onClose(); + }; + return ( + + { availableFilters.map( ( { icon, title, value: filterValue } ) => ( + + { title } + + ) ) } + + ); + } } + /> + ); +} diff --git a/client/gutenberg/extensions/tiled-gallery/gallery-image/edit.js b/client/gutenberg/extensions/tiled-gallery/gallery-image/edit.js index 3a1ca4de504fb..004f949c02e71 100644 --- a/client/gutenberg/extensions/tiled-gallery/gallery-image/edit.js +++ b/client/gutenberg/extensions/tiled-gallery/gallery-image/edit.js @@ -102,6 +102,7 @@ class GalleryImageEdit extends Component { // caption, height, id, + imageFilter, isSelected, link, linkTo, @@ -153,6 +154,7 @@ class GalleryImageEdit extends Component { className={ classnames( 'tiled-gallery__item', { 'is-selected': isSelected, 'is-transient': isBlobURL( origUrl ), + [ `filter__${ imageFilter }` ]: !! imageFilter, } ) } > { isSelected && ( diff --git a/client/gutenberg/extensions/tiled-gallery/gallery-image/save.js b/client/gutenberg/extensions/tiled-gallery/gallery-image/save.js index 6ea37ce40e827..e617c0fb1b12d 100644 --- a/client/gutenberg/extensions/tiled-gallery/gallery-image/save.js +++ b/client/gutenberg/extensions/tiled-gallery/gallery-image/save.js @@ -1,6 +1,7 @@ /** * External Dependencies */ +import classnames from 'classnames'; import { isBlobURL } from '@wordpress/blob'; /* @TODO Caption has been commented out */ @@ -11,6 +12,7 @@ export default function GalleryImageSave( props ) { 'aria-label': ariaLabel, alt, // caption, + imageFilter, height, id, link, @@ -49,7 +51,11 @@ export default function GalleryImageSave( props ) { ); return ( -
+
{ href ? { img } : img } { /* ! RichText.isEmpty( caption ) && ( diff --git a/client/gutenberg/extensions/tiled-gallery/index.js b/client/gutenberg/extensions/tiled-gallery/index.js index afc3df8a7cb12..8ee7b3d73eb93 100644 --- a/client/gutenberg/extensions/tiled-gallery/index.js +++ b/client/gutenberg/extensions/tiled-gallery/index.js @@ -57,6 +57,9 @@ const blockAttributes = { default: [], type: 'array', }, + imageFilter: { + type: 'string', + }, images: { type: 'array', default: [], diff --git a/client/gutenberg/extensions/tiled-gallery/layout/index.js b/client/gutenberg/extensions/tiled-gallery/layout/index.js index e0905ef7947b5..a3f1cde91e2f3 100644 --- a/client/gutenberg/extensions/tiled-gallery/layout/index.js +++ b/client/gutenberg/extensions/tiled-gallery/layout/index.js @@ -50,6 +50,7 @@ export default class Layout extends Component { // This is because the images are stored in an array in the block attributes. renderImage( img, i ) { const { + imageFilter, images, isSave, linkTo, @@ -71,13 +72,14 @@ export default class Layout extends Component { // caption={ img.caption } height={ img.height } id={ img.id } - origUrl={ img.url } + imageFilter={ imageFilter } isSelected={ selectedImage === i } key={ i } link={ img.link } linkTo={ linkTo } onRemove={ isSave ? undefined : onRemoveImage( i ) } onSelect={ isSave ? undefined : onSelectImage( i ) } + origUrl={ img.url } setAttributes={ isSave ? undefined : setImageAttributes( i ) } url={ this.photonize( img ) } width={ img.width } diff --git a/client/gutenberg/extensions/tiled-gallery/save.jsx b/client/gutenberg/extensions/tiled-gallery/save.jsx index 5b39c73e609f3..377776424995a 100644 --- a/client/gutenberg/extensions/tiled-gallery/save.jsx +++ b/client/gutenberg/extensions/tiled-gallery/save.jsx @@ -7,7 +7,7 @@ import { getActiveStyleName } from 'gutenberg/extensions/utils'; import { LAYOUT_STYLES } from './constants'; export default function TiledGallerySave( { attributes } ) { - const { images } = attributes; + const { imageFilter, images } = attributes; if ( ! images.length ) { return null; @@ -20,6 +20,7 @@ export default function TiledGallerySave( { attributes } ) { align={ align } className={ className } columns={ columns } + imageFilter={ imageFilter } images={ images } isSave layoutStyle={ getActiveStyleName( LAYOUT_STYLES, className ) } diff --git a/client/gutenberg/extensions/tiled-gallery/view.scss b/client/gutenberg/extensions/tiled-gallery/view.scss index 85f9b588e0719..d7e475c5d6244 100644 --- a/client/gutenberg/extensions/tiled-gallery/view.scss +++ b/client/gutenberg/extensions/tiled-gallery/view.scss @@ -1,4 +1,5 @@ @import './variables.scss'; +@import './css-gram.scss'; $tiled-gallery-max-column-count: 20; @@ -70,6 +71,26 @@ $tiled-gallery-max-column-count: 20; padding: 0; position: relative; + &.filter__black-and-white { + filter: grayscale( 100% ); + } + + &.filter__sepia { + filter: sepia( 100% ); + } + + &.filter__1977 { + @include _1977; + } + + &.filter__clarendon { + @include clarendon; + } + + &.filter__gingham { + @include gingham; + } + & + & { margin-top: $tiled-gallery-gutter; } From 788a0eec3df7d1378d4bb55355593b11eb13f686 Mon Sep 17 00:00:00 2001 From: Jeremy Herve Date: Tue, 26 Feb 2019 17:57:05 +0100 Subject: [PATCH 02/29] Jetpack Blocks: move a new set of blocks in production See https://github.com/Automattic/jetpack/milestone/119 --- .../extensions/presets/jetpack/index.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/gutenberg/extensions/presets/jetpack/index.json b/client/gutenberg/extensions/presets/jetpack/index.json index 07c7a10b268c7..5fd3f798c209e 100644 --- a/client/gutenberg/extensions/presets/jetpack/index.json +++ b/client/gutenberg/extensions/presets/jetpack/index.json @@ -1,24 +1,24 @@ { "production": [ + "business-hours", "contact-form", + "contact-info", "gif", + "mailchimp", "map", "markdown", "publicize", "related-posts", "shortlinks", "simple-payments", + "slideshow", "subscriptions", - "tiled-gallery" + "tiled-gallery", + "videopress", + "wordads" ], "beta": [ - "business-hours", - "contact-info", - "mailchimp", "repeat-visitor", - "slideshow", - "videopress", - "vr", - "wordads" + "vr" ] } From 30282bfba6bfb5835115516136c4e3726b811465 Mon Sep 17 00:00:00 2001 From: Jeremy Herve Date: Tue, 26 Feb 2019 17:58:06 +0100 Subject: [PATCH 03/29] Jetpack Blocks: tag new version of the blocks for the 7.1 release --- client/gutenberg/extensions/presets/jetpack/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/gutenberg/extensions/presets/jetpack/package.json b/client/gutenberg/extensions/presets/jetpack/package.json index 79ca190b9adac..1440e1efe5161 100644 --- a/client/gutenberg/extensions/presets/jetpack/package.json +++ b/client/gutenberg/extensions/presets/jetpack/package.json @@ -1,6 +1,6 @@ { "name": "@automattic/jetpack-blocks", - "version": "12.1.0", + "version": "13.0.0", "description": "Gutenberg blocks for the Jetpack WordPress plugin", "main": "build/editor.js", "files": [ From 93c51450e5527222a032fe143636703e36a90c36 Mon Sep 17 00:00:00 2001 From: Enej Bajgoric Date: Tue, 26 Feb 2019 09:36:08 -0800 Subject: [PATCH 04/29] Contact Info: Fix/contact info fix sidebar (#31042) * Contact Info Block: Remove the Sidebar for google maps link * bug fix: use className instead of class --- .../extensions/contact-info/address/edit.js | 20 +++-------------- .../extensions/contact-info/address/save.js | 22 ++++++++++--------- 2 files changed, 15 insertions(+), 27 deletions(-) diff --git a/client/gutenberg/extensions/contact-info/address/edit.js b/client/gutenberg/extensions/contact-info/address/edit.js index ac65a3ef684f7..bedb32b13c04d 100644 --- a/client/gutenberg/extensions/contact-info/address/edit.js +++ b/client/gutenberg/extensions/contact-info/address/edit.js @@ -2,16 +2,15 @@ * External dependencies */ import classnames from 'classnames'; -import { PlainText, InspectorControls } from '@wordpress/editor'; +import { PlainText } from '@wordpress/editor'; import { Component, Fragment } from '@wordpress/element'; -import { ToggleControl, PanelBody, ExternalLink } from '@wordpress/components'; +import { ToggleControl } from '@wordpress/components'; /** * Internal dependencies */ import { __ } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; -import ClipboardInput from 'gutenberg/extensions/presets/jetpack/utils/clipboard-input'; -import { default as save, googleMapsUrl } from './save'; +import { default as save } from './save'; class AddressEdit extends Component { constructor( ...args ) { @@ -116,19 +115,6 @@ class AddressEdit extends Component { onKeyDown={ this.preventEnterKey } /> { externalLink } - - - { externalLink } - { hasContent && } - { hasContent && ( -
- - { __( 'Visit Google Maps' ) } - -
- ) } -
-
) } diff --git a/client/gutenberg/extensions/contact-info/address/save.js b/client/gutenberg/extensions/contact-info/address/save.js index 554e89171050c..54957ef0aa549 100644 --- a/client/gutenberg/extensions/contact-info/address/save.js +++ b/client/gutenberg/extensions/contact-info/address/save.js @@ -17,35 +17,37 @@ const Address = ( { attributes: { address, addressLine2, addressLine3, city, region, postal, country }, } ) => ( - { address &&
{ address }
} + { address && ( +
{ address }
+ ) } { addressLine2 && ( -
{ addressLine2 }
+
{ addressLine2 }
) } { addressLine3 && ( -
{ addressLine3 }
+
{ addressLine3 }
) } - { city && ! ( region || postal ) &&
{ city }
} + { city && ! ( region || postal ) &&
{ city }
} { city && ( region || postal ) && (
{ [ - { city }, + { city }, ', ', - { region }, + { region }, ' ', - { postal }, + { postal }, ] }
) } { ! city && ( region || postal ) && (
{ [ - { region }, + { region }, ' ', - { postal }, + { postal }, ] }
) } - { country &&
{ country }
} + { country &&
{ country }
}
); From 98c558f72fb495b91899265f8752ed6dcd9d09cf Mon Sep 17 00:00:00 2001 From: Jefferson Rabb Date: Tue, 26 Feb 2019 15:35:15 -0500 Subject: [PATCH 05/29] Additional keywords for the Slideshow block. (#31038) --- client/gutenberg/extensions/slideshow/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/gutenberg/extensions/slideshow/index.js b/client/gutenberg/extensions/slideshow/index.js index b401aeb5ecb16..4a33de4f611c2 100644 --- a/client/gutenberg/extensions/slideshow/index.js +++ b/client/gutenberg/extensions/slideshow/index.js @@ -71,7 +71,7 @@ export const name = 'slideshow'; export const settings = { title: __( 'Slideshow' ), category: 'jetpack', - keywords: [ __( 'image' ) ], + keywords: [ __( 'image' ), __( 'gallery' ), __( 'slider' ) ], description: __( 'Add an interactive slideshow.' ), attributes, supports: { From be77dcb6a0610cfea32827a5c9231296aa10af96 Mon Sep 17 00:00:00 2001 From: Jefferson Rabb Date: Tue, 26 Feb 2019 17:14:28 -0500 Subject: [PATCH 06/29] Improvement to Autoplay delay label. (#31039) --- client/gutenberg/extensions/slideshow/edit.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/gutenberg/extensions/slideshow/edit.js b/client/gutenberg/extensions/slideshow/edit.js index 329b689837e16..744954e6a2fe0 100644 --- a/client/gutenberg/extensions/slideshow/edit.js +++ b/client/gutenberg/extensions/slideshow/edit.js @@ -112,7 +112,7 @@ class SlideshowEdit extends Component { /> { autoplay && ( { setAttributes( { delay: value } ); From 00075b81e9480fc2b2f8211de29dd7038fa5ecec Mon Sep 17 00:00:00 2001 From: Jefferson Rabb Date: Tue, 26 Feb 2019 17:27:12 -0500 Subject: [PATCH 07/29] Slideshow: Add New Uploads At End (#31046) * Add newly uploaded images to the end of the slideshow. Jump to the position of the new upload so user sees upload status. * Alternate approach using comparison of image array length in componentDidUpdate to determine position. --- client/gutenberg/extensions/slideshow/edit.js | 2 +- client/gutenberg/extensions/slideshow/slideshow.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/client/gutenberg/extensions/slideshow/edit.js b/client/gutenberg/extensions/slideshow/edit.js index 744954e6a2fe0..11c4d2ebb36f2 100644 --- a/client/gutenberg/extensions/slideshow/edit.js +++ b/client/gutenberg/extensions/slideshow/edit.js @@ -75,7 +75,7 @@ class SlideshowEdit extends Component { onFileChange: images => { const imagesNormalized = images.map( image => pickRelevantMediaFiles( image ) ); setAttributes( { - images: [ ...imagesNormalized, ...currentImages ], + images: [ ...currentImages, ...imagesNormalized ], } ); if ( ! imagesNormalized.every( image => isBlobURL( image.url ) ) ) { unlockPostSaving( lockName ); diff --git a/client/gutenberg/extensions/slideshow/slideshow.js b/client/gutenberg/extensions/slideshow/slideshow.js index d3ada7e4c3bef..a11a799fc1727 100644 --- a/client/gutenberg/extensions/slideshow/slideshow.js +++ b/client/gutenberg/extensions/slideshow/slideshow.js @@ -63,7 +63,10 @@ class Slideshow extends Component { delay !== prevProps.delay || images !== prevProps.images ) { - const realIndex = images !== prevProps.images ? 0 : this.swiperInstance.realIndex; + const realIndex = + images.length === prevProps.images.length + ? this.swiperInstance.realIndex + : prevProps.images.length; this.swiperInstance && this.swiperInstance.destroy( true, true ); this.buildSwiper( realIndex ).then( swiper => { this.swiperInstance = swiper; From 6bf700cfea6d6f0c58739432aee7506c20f120de Mon Sep 17 00:00:00 2001 From: Enej Bajgoric Date: Tue, 26 Feb 2019 15:14:22 -0800 Subject: [PATCH 08/29] Contact Info: Add the ability to add the buisness hours block to the contact info (#31056) --- client/gutenberg/extensions/contact-info/edit.js | 1 + 1 file changed, 1 insertion(+) diff --git a/client/gutenberg/extensions/contact-info/edit.js b/client/gutenberg/extensions/contact-info/edit.js index e3e1ceb03d8dc..7960eef9ab379 100644 --- a/client/gutenberg/extensions/contact-info/edit.js +++ b/client/gutenberg/extensions/contact-info/edit.js @@ -13,6 +13,7 @@ const ALLOWED_BLOCKS = [ 'jetpack/email', 'jetpack/phone', 'jetpack/map', + 'jetpack/business-hours', 'core/paragraph', 'core/image', 'core/heading', From d6a238a0a0cd36de4633eae5be85917b03240a2e Mon Sep 17 00:00:00 2001 From: Enej Bajgoric Date: Wed, 27 Feb 2019 09:14:25 -0800 Subject: [PATCH 09/29] Contact Info Block: Improve email validation (#31033) * Contact Info Block: Improve the email validation By using the emailValidator that is use in more places we can provide better matching and of email addresses. * bug fix. take into account any number of punctuation. --- .../extensions/contact-info/email/save.js | 37 +++++++++++++------ 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/client/gutenberg/extensions/contact-info/email/save.js b/client/gutenberg/extensions/contact-info/email/save.js index e14da6e3813fe..f6b9312d9ea49 100644 --- a/client/gutenberg/extensions/contact-info/email/save.js +++ b/client/gutenberg/extensions/contact-info/email/save.js @@ -1,18 +1,33 @@ /** - * Internal dependencies + * External dependencies */ -import textMatchReplace from 'gutenberg/extensions/presets/jetpack/utils/text-match-replace'; +import emailValidator from 'email-validator'; +import { Fragment } from '@wordpress/element'; const renderEmail = inputText => { - return textMatchReplace( - inputText, - /((?:[a-z|0-9+_](?:\.|_\+)*)+[a-z|0-9]\@(?:[a-z|0-9])+(?:(?:\.){0,1}[a-z|0-9]){2}\.[a-z]{2,22})/gim, - ( email, i ) => ( - - { email } - - ) - ); + const explodedInput = inputText.split( /(\s+)/ ).map( ( email, i ) => { + // Remove and punctuation from the end of the email address. + const emailToValidate = email.replace( /([.,\/#!$%\^&\*;:{}=\-_`~()\]\[])+$/g, '' ); + if ( email.indexOf( '@' ) && emailValidator.validate( emailToValidate ) ) { + return email === emailToValidate ? ( + // Email. + + { email } + + ) : ( + // Email with punctionation. + + + { emailToValidate } + + { email.slice( -( email.length - emailToValidate.length ) ) } + + ); + } + // Just a plain string. + return { email }; + } ); + return explodedInput; }; const save = ( { attributes: { email }, className } ) => From cbba4d6607869ed70a35116c8e31799e1b34f802 Mon Sep 17 00:00:00 2001 From: Rocco Tripaldi Date: Wed, 27 Feb 2019 13:06:05 -0500 Subject: [PATCH 10/29] Business hours: show 'closed' when data is incomplete for a given interval (#31083) * Business hours If data is incomplete for a given interval, display 'Closed' or null; * adjusting logic - thanks @lezama * further improved time validation logic --- .../business-hours/components/day-save.jsx | 28 +++++++++++-------- .../business-hours/components/day.jsx | 2 ++ 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/client/gutenberg/extensions/business-hours/components/day-save.jsx b/client/gutenberg/extensions/business-hours/components/day-save.jsx index 7af57956f6608..146a9dc6a8763 100644 --- a/client/gutenberg/extensions/business-hours/components/day-save.jsx +++ b/client/gutenberg/extensions/business-hours/components/day-save.jsx @@ -16,6 +16,9 @@ class DaySave extends Component { const { timeFormat } = this.props; const [ hours, minutes ] = time.split( ':' ); const _date = new Date(); + if ( ! hours || ! minutes ) { + return false; + } _date.setHours( hours ); _date.setMinutes( minutes ); return date( timeFormat, _date ); @@ -23,28 +26,29 @@ class DaySave extends Component { renderInterval = ( interval, key ) => { return ( - ! isEmpty( interval.opening ) && - ! isEmpty( interval.closing ) && ( -
- { sprintf( - _x( 'From %s to %s', 'from business opening hour to closing hour' ), - this.formatTime( interval.opening ), - this.formatTime( interval.closing ) - ) } -
- ) +
+ { sprintf( + _x( 'From %s to %s', 'from business opening hour to closing hour' ), + this.formatTime( interval.opening ), + this.formatTime( interval.closing ) + ) } +
); }; render() { const { day, localization } = this.props; + const hours = day.hours.filter( + // remove any malformed or empty intervals + interval => this.formatTime( interval.opening ) && this.formatTime( interval.closing ) + ); return (
{ localization.days[ day.name ] }
- { isEmpty( day.hours ) ? ( + { isEmpty( hours ) ? (
{ _x( 'Closed', 'business is closed on a full day' ) }
) : ( - day.hours.map( this.renderInterval ) + hours.map( this.renderInterval ) ) }
); diff --git a/client/gutenberg/extensions/business-hours/components/day.jsx b/client/gutenberg/extensions/business-hours/components/day.jsx index 429943b1ffac4..58a03799238fd 100644 --- a/client/gutenberg/extensions/business-hours/components/day.jsx +++ b/client/gutenberg/extensions/business-hours/components/day.jsx @@ -30,6 +30,7 @@ class Day extends Component { label={ __( 'Opening' ) } value={ opening } className="business-hours__open" + placeHolder={ defaultOpen } onChange={ value => { this.setHour( value, 'opening', intervalIndex ); } } @@ -39,6 +40,7 @@ class Day extends Component { label={ __( 'Closing' ) } value={ closing } className="business-hours__close" + placeHolder={ defaultClose } onChange={ value => { this.setHour( value, 'closing', intervalIndex ); } } From 7ca9928b93c3f2037cf377044818dbbd409fd845 Mon Sep 17 00:00:00 2001 From: Enej Bajgoric Date: Wed, 27 Feb 2019 10:06:26 -0800 Subject: [PATCH 11/29] Contact Info Block: Split phone numbers into prefix and phone number (#31026) * Split phone numbers into prefix and phone number This allows us to be not so strict with what a phone number is and still offer a way to prefix. things. * Fix typos and simplify selection of first character. --- .../extensions/contact-info/phone/save.js | 53 ++++++++++++------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/client/gutenberg/extensions/contact-info/phone/save.js b/client/gutenberg/extensions/contact-info/phone/save.js index c0fb3d98a54f9..50f6791464a06 100644 --- a/client/gutenberg/extensions/contact-info/phone/save.js +++ b/client/gutenberg/extensions/contact-info/phone/save.js @@ -1,29 +1,44 @@ /** * Internal dependencies */ -import textMatchReplace from 'gutenberg/extensions/presets/jetpack/utils/text-match-replace'; export function renderPhone( inputText ) { - return textMatchReplace( - inputText, - /([0-9\()+]{1}[\ \-().]?[0-9]{1,6}[\ \-().]?[0-9]{0,6}[\ \-()]?[0-9]{0,6}[\ \-().]?[0-9]{0,6}[\ \-().]?[0-9]{0,6}[\ \-().]?[0-9]{0,6})/g, - ( number, i ) => { - if ( number.trim() === '' ) { - return number; - } - let justNumber = number.replace( /\D/g, '' ); - // Phone numbers starting with + shoud be part of the number. - if ( number.substring( 0, 1 ) === '+' ) { - justNumber = '+' + justNumber; - } + const arrayOfNumbers = inputText.match( /\d+\.\d+|\d+\b|\d+(?=\w)/g ); + if ( ! arrayOfNumbers ) { + // No numbers found + return inputText; + } + const indexOfFirstNumber = inputText.indexOf( arrayOfNumbers[ 0 ] ); - return ( - - { number } - - ); + // Assume that eveything after the first number should be part of the phone number. + // care about the first prefix character. + let phoneNumber = indexOfFirstNumber ? inputText.substring( indexOfFirstNumber - 1 ) : inputText; + let prefix = indexOfFirstNumber ? inputText.substring( 0, indexOfFirstNumber ) : ''; + + let justNumber = phoneNumber.replace( /\D/g, '' ); + // Phone numbers starting with + should be part of the number. + if ( /[0-9/+/(]/.test( phoneNumber[ 0 ] ) ) { + // Remove the special character from the prefix so they don't appear twice. + prefix = prefix.slice( 0, -1 ); + // Phone numbers starting with + shoud be part of the number. + if ( phoneNumber[ 0 ] === '+' ) { + justNumber = '+' + justNumber; } - ); + } else { + // Remove the first character. + phoneNumber = phoneNumber.substring( 1 ); + } + const prefixSpan = prefix.trim() ? ( + + { prefix } + + ) : null; + return [ + prefixSpan, + + { phoneNumber } + , + ]; } const save = ( { attributes: { phone }, className } ) => From 82f717d26f0da1c87c136160a901f8e6a2767721 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Thu, 28 Feb 2019 09:40:55 +0100 Subject: [PATCH 12/29] WordAds block: Update icon (#31106) --- client/gutenberg/extensions/wordads/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/gutenberg/extensions/wordads/index.js b/client/gutenberg/extensions/wordads/index.js index 6c28f75bb2f04..340570195feb7 100644 --- a/client/gutenberg/extensions/wordads/index.js +++ b/client/gutenberg/extensions/wordads/index.js @@ -17,7 +17,7 @@ export const title = __( 'Ad' ); export const icon = ( - + ); From ada224d2555998921bc448d9d88cf3d883452895 Mon Sep 17 00:00:00 2001 From: Thomas Guillot Date: Wed, 27 Feb 2019 17:50:53 +0000 Subject: [PATCH 13/29] Business Hours: Update editor styles for consistency with UI elements --- .../business-hours/components/day.jsx | 8 +------ .../extensions/business-hours/editor.scss | 22 +++++-------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/client/gutenberg/extensions/business-hours/components/day.jsx b/client/gutenberg/extensions/business-hours/components/day.jsx index 58a03799238fd..9245c38c84111 100644 --- a/client/gutenberg/extensions/business-hours/components/day.jsx +++ b/client/gutenberg/extensions/business-hours/components/day.jsx @@ -63,13 +63,7 @@ class Day extends Component {
 
- + { __( 'Add Hours' ) }
diff --git a/client/gutenberg/extensions/business-hours/editor.scss b/client/gutenberg/extensions/business-hours/editor.scss index ce03966b7cc78..9eaa449f994ee 100644 --- a/client/gutenberg/extensions/business-hours/editor.scss +++ b/client/gutenberg/extensions/business-hours/editor.scss @@ -9,7 +9,6 @@ $break-small: 600px; .business-hours__row { display: flex; - align-items: center; &.business-hours-row__add, &.business-hours-row__closed { @@ -22,8 +21,7 @@ $break-small: 600px; align-items: baseline; .business-hours__day-name { - width: 40%; - font-size: small; + width: 60%; font-weight: bold; overflow-x: hidden; text-overflow: ellipsis; @@ -33,10 +31,6 @@ $break-small: 600px; .components-form-toggle { margin-right: 4px; } - - .components-toggle-control__label { - font-size: smaller; - } } .business-hours__hours { @@ -56,21 +50,16 @@ $break-small: 600px; .components-base-control__label { margin-bottom: 0; - font-size: smaller; - } - - .components-text-control__input { - font-size: smaller; - padding: 4px; } } } } .business-hours__remove { - width: 10%; + align-self: flex-end; + margin-bottom: 8px; text-align: center; - margin-top: 16px; + width: 10%; } .business-hours-row__add button { @@ -81,7 +70,8 @@ $break-small: 600px; } .business-hours__remove button { - display: inline; + display: block; + margin: 0 auto; } .business-hours-row__add .components-button.is-default:hover, From 172079fce6ca0cfa895c80df9adce8ab5f52f771 Mon Sep 17 00:00:00 2001 From: Rocco Tripaldi Date: Thu, 28 Feb 2019 08:56:25 -0500 Subject: [PATCH 14/29] Business Hours Block: add search keywords (#31090) * Business Hours Block: add search keywords * updating terms after feedback from co-workers --- client/gutenberg/extensions/business-hours/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/gutenberg/extensions/business-hours/index.js b/client/gutenberg/extensions/business-hours/index.js index 62ca55d01e5a2..6c62347628024 100644 --- a/client/gutenberg/extensions/business-hours/index.js +++ b/client/gutenberg/extensions/business-hours/index.js @@ -6,7 +6,7 @@ import { Path } from '@wordpress/components'; /** * Internal dependencies */ -import { __ } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; +import { __, _x } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; import renderMaterialIcon from 'gutenberg/extensions/presets/jetpack/utils/render-material-icon'; import './editor.scss'; @@ -30,7 +30,11 @@ export const settings = { supports: { html: true, }, - + keywords: [ + _x( 'opening hours', 'block search term' ), + _x( 'closing time', 'block search term' ), + _x( 'schedule', 'block search term' ), + ], attributes: { days: { type: 'array', From 99c12a5bdb284353ef4ba47a76f52a05086404f2 Mon Sep 17 00:00:00 2001 From: Jeremy Herve Date: Thu, 28 Feb 2019 21:22:29 +0100 Subject: [PATCH 15/29] Related Posts: update the message displayed when no related posts (#31126) Discussion: p8oabR-kb-p2 #comment-2590 --- client/gutenberg/extensions/related-posts/edit.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/gutenberg/extensions/related-posts/edit.jsx b/client/gutenberg/extensions/related-posts/edit.jsx index 230f5f3d2dcb9..9a3b021e2ab0f 100644 --- a/client/gutenberg/extensions/related-posts/edit.jsx +++ b/client/gutenberg/extensions/related-posts/edit.jsx @@ -23,7 +23,7 @@ function PlaceholderPostEdit( props ) { aria-labelledby={ props.id + '-heading' } > - { __( 'Preview: Not enough related posts found' ) } + { __( "Preview unavailable: you haven't published enough posts with similar content." ) } { props.displayThumbnails && (
Date: Fri, 1 Mar 2019 08:27:43 +0100 Subject: [PATCH 16/29] Tiled Gallery: Remove i18n strings in save (#31119) * Add deprecated declaration based on #30724 * Remove localized aria-label from save --- .../tiled-gallery/deprecated/v1/constants.js | 27 ++ .../tiled-gallery/deprecated/v1/image.js | 51 ++++ .../tiled-gallery/deprecated/v1/index.js | 81 +++++ .../deprecated/v1/layout/column.js | 3 + .../deprecated/v1/layout/gallery.js | 7 + .../deprecated/v1/layout/index.js | 141 +++++++++ .../deprecated/v1/layout/mosaic/index.js | 104 +++++++ .../deprecated/v1/layout/mosaic/ratios.js | 280 ++++++++++++++++++ .../deprecated/v1/layout/mosaic/resize.js | 107 +++++++ .../tiled-gallery/deprecated/v1/layout/row.js | 8 + .../deprecated/v1/layout/square.js | 33 +++ .../tiled-gallery/deprecated/v1/save.js | 31 ++ .../tiled-gallery/gallery-image/save.js | 2 - .../extensions/tiled-gallery/index.js | 3 + 14 files changed, 876 insertions(+), 2 deletions(-) create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/constants.js create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/image.js create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/index.js create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/column.js create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/gallery.js create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/index.js create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/index.js create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/ratios.js create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/resize.js create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/row.js create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/square.js create mode 100644 client/gutenberg/extensions/tiled-gallery/deprecated/v1/save.js diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/constants.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/constants.js new file mode 100644 index 0000000000000..55a451fccf618 --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/constants.js @@ -0,0 +1,27 @@ +export const ALLOWED_MEDIA_TYPES = [ 'image' ]; +export const GUTTER_WIDTH = 4; +export const MAX_COLUMNS = 20; +export const PHOTON_MAX_RESIZE = 2000; + +/** + * Layouts + */ +export const LAYOUT_CIRCLE = 'circle'; +export const LAYOUT_COLUMN = 'columns'; +export const LAYOUT_DEFAULT = 'rectangular'; +export const LAYOUT_SQUARE = 'square'; +export const LAYOUT_STYLES = [ + { + isDefault: true, + name: LAYOUT_DEFAULT, + }, + { + name: LAYOUT_CIRCLE, + }, + { + name: LAYOUT_SQUARE, + }, + { + name: LAYOUT_COLUMN, + }, +]; diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/image.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/image.js new file mode 100644 index 0000000000000..61d4a2cd05cef --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/image.js @@ -0,0 +1,51 @@ +/** + * External Dependencies + */ +import { isBlobURL } from '@wordpress/blob'; + +export default function GalleryImageSave( props ) { + const { + 'aria-label': ariaLabel, + alt, + // caption, + height, + id, + link, + linkTo, + origUrl, + url, + width, + } = props; + + if ( isBlobURL( origUrl ) ) { + return null; + } + + let href; + + switch ( linkTo ) { + case 'media': + href = url; + break; + case 'attachment': + href = link; + break; + } + + const img = ( + { + ); + + return ( +
{ href ? { img } : img }
+ ); +} diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/index.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/index.js new file mode 100644 index 0000000000000..69539d007cdef --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/index.js @@ -0,0 +1,81 @@ +/** + * Internal dependencies + */ +export { default as save } from './save'; +import { LAYOUT_DEFAULT } from './constants'; + +export const attributes = { + // Set default align + align: { + default: 'center', + type: 'string', + }, + // Set default className (used with block styles) + className: { + default: `is-style-${ LAYOUT_DEFAULT }`, + type: 'string', + }, + columns: { + type: 'number', + }, + ids: { + default: [], + type: 'array', + }, + images: { + type: 'array', + default: [], + source: 'query', + selector: '.tiled-gallery__item', + query: { + alt: { + attribute: 'alt', + default: '', + selector: 'img', + source: 'attribute', + }, + caption: { + selector: 'figcaption', + source: 'html', + type: 'string', + }, + height: { + attribute: 'data-height', + selector: 'img', + source: 'attribute', + type: 'number', + }, + id: { + attribute: 'data-id', + selector: 'img', + source: 'attribute', + }, + link: { + attribute: 'data-link', + selector: 'img', + source: 'attribute', + }, + url: { + attribute: 'data-url', + selector: 'img', + source: 'attribute', + }, + width: { + attribute: 'data-width', + selector: 'img', + source: 'attribute', + type: 'number', + }, + }, + }, + linkTo: { + default: 'none', + type: 'string', + }, +}; + +export const support = { + align: [ 'center', 'wide', 'full' ], + customClassName: false, + html: false, +}; diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/column.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/column.js new file mode 100644 index 0000000000000..a3ed5cdf04cbb --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/column.js @@ -0,0 +1,3 @@ +export default function Column( { children } ) { + return
{ children }
; +} diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/gallery.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/gallery.js new file mode 100644 index 0000000000000..94fc61e4be980 --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/gallery.js @@ -0,0 +1,7 @@ +export default function Gallery( { children, galleryRef } ) { + return ( +
+ { children } +
+ ); +} diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/index.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/index.js new file mode 100644 index 0000000000000..6492d78811c46 --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/index.js @@ -0,0 +1,141 @@ +/** + * External dependencies + */ +import photon from 'photon'; +import { __ } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; +import { Component } from '@wordpress/element'; +import { format as formatUrl, parse as parseUrl } from 'url'; +import { isBlobURL } from '@wordpress/blob'; +import { sprintf } from '@wordpress/i18n'; + +/** + * Internal dependencies + */ +import Image from '../image'; +import Mosaic from './mosaic'; +import Square from './square'; +import { PHOTON_MAX_RESIZE } from '../constants'; + +export default class Layout extends Component { + photonize( { height, width, url } ) { + if ( ! url ) { + return; + } + + // Do not Photonize images that are still uploading or from localhost + if ( isBlobURL( url ) || /^https?:\/\/localhost/.test( url ) ) { + return url; + } + + // Drop query args, photon URLs can't handle them + // This should be the "raw" url, we'll add dimensions later + const cleanUrl = url.split( '?', 1 )[ 0 ]; + + const photonImplementation = isWpcomFilesUrl( url ) ? photonWpcomImage : photon; + + const { layoutStyle } = this.props; + + if ( isSquareishLayout( layoutStyle ) && width && height ) { + const size = Math.min( PHOTON_MAX_RESIZE, width, height ); + return photonImplementation( cleanUrl, { resize: `${ size },${ size }` } ); + } + return photonImplementation( cleanUrl ); + } + + // This is tricky: + // - We need to "photonize" to resize the images at appropriate dimensions + // - The resize will depend on the image size and the layout in some cases + // - Handlers need to be created by index so that the image changes can be applied correctly. + // This is because the images are stored in an array in the block attributes. + renderImage( img, i ) { + const { images, linkTo, selectedImage } = this.props; + + /* translators: %1$d is the order number of the image, %2$d is the total number of images. */ + const ariaLabel = sprintf( __( 'image %1$d of %2$d in gallery' ), i + 1, images.length ); + return ( + { + ); + } + + render() { + const { align, children, className, columns, images, layoutStyle } = this.props; + + const LayoutRenderer = isSquareishLayout( layoutStyle ) ? Square : Mosaic; + + const renderedImages = this.props.images.map( this.renderImage, this ); + + return ( +
+ + { children } +
+ ); + } +} + +function isSquareishLayout( layout ) { + return [ 'circle', 'square' ].includes( layout ); +} + +function isWpcomFilesUrl( url ) { + const { host } = parseUrl( url ); + return /\.files\.wordpress\.com$/.test( host ); +} + +/** + * Apply photon arguments to *.files.wordpress.com images + * + * This function largely duplicates the functionlity of the photon.js lib. + * This is necessary because we want to serve images from *.files.wordpress.com so that private + * WordPress.com sites can use this block which depends on a Photon-like image service. + * + * If we pass all images through Photon servers, some images are unreachable. *.files.wordpress.com + * is already photon-like so we can pass it the same parameters for image resizing. + * + * @param {string} url Image url + * @param {Object} opts Options to pass to photon + * + * @return {string} Url string with options applied + */ +function photonWpcomImage( url, opts = {} ) { + // Adhere to the same options API as the photon.js lib + const photonLibMappings = { + width: 'w', + height: 'h', + letterboxing: 'lb', + removeLetterboxing: 'ulb', + }; + + // Discard some param parts + const { auth, hash, port, query, search, ...urlParts } = parseUrl( url ); + + // Build query + // This reduction intentionally mutates the query as it is built internally. + urlParts.query = Object.keys( opts ).reduce( + ( q, key ) => + Object.assign( q, { + [ photonLibMappings.hasOwnProperty( key ) ? photonLibMappings[ key ] : key ]: opts[ key ], + } ), + {} + ); + + return formatUrl( urlParts ); +} diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/index.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/index.js new file mode 100644 index 0000000000000..8c56b1641dd1e --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/index.js @@ -0,0 +1,104 @@ +/** + * External dependencies + */ +import { Component, createRef } from '@wordpress/element'; +import ResizeObserver from 'resize-observer-polyfill'; + +/** + * Internal dependencies + */ +import Column from '../column'; +import Gallery from '../gallery'; +import Row from '../row'; +import { getGalleryRows, handleRowResize } from './resize'; +import { imagesToRatios, ratiosToColumns, ratiosToMosaicRows } from './ratios'; + +export default class Mosaic extends Component { + gallery = createRef(); + pendingRaf = null; + ro = null; // resizeObserver instance + + componentDidMount() { + this.observeResize(); + } + + componentWillUnmount() { + this.unobserveResize(); + } + + componentDidUpdate( prevProps ) { + if ( prevProps.images !== this.props.images || prevProps.align !== this.props.align ) { + this.triggerResize(); + } else if ( 'columns' === this.props.layoutStyle && prevProps.columns !== this.props.columns ) { + this.triggerResize(); + } + } + + handleGalleryResize = entries => { + if ( this.pendingRaf ) { + cancelAnimationFrame( this.pendingRaf ); + this.pendingRaf = null; + } + this.pendingRaf = requestAnimationFrame( () => { + for ( const { contentRect, target } of entries ) { + const { width } = contentRect; + getGalleryRows( target ).forEach( row => handleRowResize( row, width ) ); + } + } ); + }; + + triggerResize() { + if ( this.gallery.current ) { + this.handleGalleryResize( [ + { + target: this.gallery.current, + contentRect: { width: this.gallery.current.clientWidth }, + }, + ] ); + } + } + + observeResize() { + this.triggerResize(); + this.ro = new ResizeObserver( this.handleGalleryResize ); + if ( this.gallery.current ) { + this.ro.observe( this.gallery.current ); + } + } + + unobserveResize() { + if ( this.ro ) { + this.ro.disconnect(); + this.ro = null; + } + if ( this.pendingRaf ) { + cancelAnimationFrame( this.pendingRaf ); + this.pendingRaf = null; + } + } + + render() { + const { align, columns, images, layoutStyle, renderedImages } = this.props; + + const ratios = imagesToRatios( images ); + const rows = + 'columns' === layoutStyle + ? ratiosToColumns( ratios, columns ) + : ratiosToMosaicRows( ratios, { isWide: [ 'full', 'wide' ].includes( align ) } ); + + let cursor = 0; + return ( + + { rows.map( ( row, rowIndex ) => ( + + { row.map( ( colSize, colIndex ) => { + const columnImages = renderedImages.slice( cursor, cursor + colSize ); + cursor += colSize; + return { columnImages }; + } ) } + + ) ) } + + ); + } +} diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/ratios.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/ratios.js new file mode 100644 index 0000000000000..8accd552b710a --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/ratios.js @@ -0,0 +1,280 @@ +/** + * External dependencies + */ +import { + drop, + every, + isEqual, + map, + overEvery, + some, + sum, + take, + takeRight, + takeWhile, + zipWith, +} from 'lodash'; + +export function imagesToRatios( images ) { + return map( images, ratioFromImage ); +} + +export function ratioFromImage( { height, width } ) { + return height && width ? width / height : 1; +} + +/** + * Build three columns, each of which should contain approximately 1/3 of the total ratio + * + * @param {Array.} ratios Ratios of images put into shape + * @param {number} columnCount Number of columns + * + * @return {Array.>} Shape of rows and columns + */ +export function ratiosToColumns( ratios, columnCount ) { + // If we don't have more than 1 per column, just return a simple 1 ratio per column shape + if ( ratios.length <= columnCount ) { + return [ Array( ratios.length ).fill( 1 ) ]; + } + + const total = sum( ratios ); + const targetColRatio = total / columnCount; + + const row = []; + let toProcess = ratios; + let accumulatedRatio = 0; + + // We skip the last column in the loop and add rest later + for ( let i = 0; i < columnCount - 1; i++ ) { + const colSize = takeWhile( toProcess, ratio => { + const shouldTake = accumulatedRatio <= ( i + 1 ) * targetColRatio; + if ( shouldTake ) { + accumulatedRatio += ratio; + } + return shouldTake; + } ).length; + row.push( colSize ); + toProcess = drop( toProcess, colSize ); + } + + // Don't calculate last column, just add what's left + row.push( toProcess.length ); + + // A shape is an array of rows. Wrap our row in an array. + return [ row ]; +} + +/** + * These are partially applied functions. + * They rely on helper function (defined below) to create a function that expects to be passed ratios + * during processing. + * + * …FitsNextImages() functions should be passed ratios to be processed + * …IsNotRecent() functions should be passed the processed shapes + */ + +const reverseSymmetricRowIsNotRecent = isNotRecentShape( [ 2, 1, 2 ], 5 ); +const reverseSymmetricFitsNextImages = checkNextRatios( [ + isLandscape, + isLandscape, + isPortrait, + isLandscape, + isLandscape, +] ); +const longSymmetricRowFitsNextImages = checkNextRatios( [ + isLandscape, + isLandscape, + isLandscape, + isPortrait, + isLandscape, + isLandscape, + isLandscape, +] ); +const longSymmetricRowIsNotRecent = isNotRecentShape( [ 3, 1, 3 ], 5 ); +const symmetricRowFitsNextImages = checkNextRatios( [ + isPortrait, + isLandscape, + isLandscape, + isPortrait, +] ); +const symmetricRowIsNotRecent = isNotRecentShape( [ 1, 2, 1 ], 5 ); +const oneThreeFitsNextImages = checkNextRatios( [ + isPortrait, + isLandscape, + isLandscape, + isLandscape, +] ); +const oneThreeIsNotRecent = isNotRecentShape( [ 1, 3 ], 3 ); +const threeOneIsFitsNextImages = checkNextRatios( [ + isLandscape, + isLandscape, + isLandscape, + isPortrait, +] ); +const threeOneIsNotRecent = isNotRecentShape( [ 3, 1 ], 3 ); +const oneTwoFitsNextImages = checkNextRatios( [ + lt( 1.6 ), + overEvery( gte( 0.9 ), lt( 2 ) ), + overEvery( gte( 0.9 ), lt( 2 ) ), +] ); +const oneTwoIsNotRecent = isNotRecentShape( [ 1, 2 ], 3 ); +const fiveIsNotRecent = isNotRecentShape( [ 1, 1, 1, 1, 1 ], 1 ); +const fourIsNotRecent = isNotRecentShape( [ 1, 1, 1, 1 ], 1 ); +const threeIsNotRecent = isNotRecentShape( [ 1, 1, 1 ], 3 ); +const twoOneFitsNextImages = checkNextRatios( [ + overEvery( gte( 0.9 ), lt( 2 ) ), + overEvery( gte( 0.9 ), lt( 2 ) ), + lt( 1.6 ), +] ); +const twoOneIsNotRecent = isNotRecentShape( [ 2, 1 ], 3 ); +const panoramicFitsNextImages = checkNextRatios( [ isPanoramic ] ); + +export function ratiosToMosaicRows( ratios, { isWide } = {} ) { + // This function will recursively process the input until it is consumed + const go = ( processed, toProcess ) => { + if ( ! toProcess.length ) { + return processed; + } + + let next; + + if ( + /* Reverse_Symmetric_Row */ + toProcess.length > 15 && + reverseSymmetricFitsNextImages( toProcess ) && + reverseSymmetricRowIsNotRecent( processed ) + ) { + next = [ 2, 1, 2 ]; + } else if ( + /* Long_Symmetric_Row */ + toProcess.length > 15 && + longSymmetricRowFitsNextImages( toProcess ) && + longSymmetricRowIsNotRecent( processed ) + ) { + next = [ 3, 1, 3 ]; + } else if ( + /* Symmetric_Row */ + toProcess.length !== 5 && + symmetricRowFitsNextImages( toProcess ) && + symmetricRowIsNotRecent( processed ) + ) { + next = [ 1, 2, 1 ]; + } else if ( + /* One_Three */ + oneThreeFitsNextImages( toProcess ) && + oneThreeIsNotRecent( processed ) + ) { + next = [ 1, 3 ]; + } else if ( + /* Three_One */ + threeOneIsFitsNextImages( toProcess ) && + threeOneIsNotRecent( processed ) + ) { + next = [ 3, 1 ]; + } else if ( + /* One_Two */ + oneTwoFitsNextImages( toProcess ) && + oneTwoIsNotRecent( processed ) + ) { + next = [ 1, 2 ]; + } else if ( + /* Five */ + isWide && + ( toProcess.length === 5 || ( toProcess.length !== 10 && toProcess.length > 6 ) ) && + fiveIsNotRecent( processed ) && + sum( take( toProcess, 5 ) ) < 5 + ) { + next = [ 1, 1, 1, 1, 1 ]; + } else if ( + /* Four */ + isFourValidCandidate( processed, toProcess ) + ) { + next = [ 1, 1, 1, 1 ]; + } else if ( + /* Three */ + isThreeValidCandidate( processed, toProcess, isWide ) + ) { + next = [ 1, 1, 1 ]; + } else if ( + /* Two_One */ + twoOneFitsNextImages( toProcess ) && + twoOneIsNotRecent( processed ) + ) { + next = [ 2, 1 ]; + } else if ( /* Panoramic */ panoramicFitsNextImages( toProcess ) ) { + next = [ 1 ]; + } else if ( /* One_One */ toProcess.length > 3 ) { + next = [ 1, 1 ]; + } else { + // Everything left + next = Array( toProcess.length ).fill( 1 ); + } + + // Add row + const nextProcessed = processed.concat( [ next ] ); + + // Trim consumed images from next processing step + const consumedImages = sum( next ); + const nextToProcess = toProcess.slice( consumedImages ); + + return go( nextProcessed, nextToProcess ); + }; + return go( [], ratios ); +} + +function isThreeValidCandidate( processed, toProcess, isWide ) { + const ratio = sum( take( toProcess, 3 ) ); + return ( + toProcess.length >= 3 && + toProcess.length !== 4 && + toProcess.length !== 6 && + threeIsNotRecent( processed ) && + ( ratio < 2.5 || + ( ratio < 5 && + /* nextAreSymettric */ + ( toProcess.length >= 3 && + /* @FIXME floating point equality?? */ toProcess[ 0 ] === toProcess[ 2 ] ) ) || + isWide ) + ); +} + +function isFourValidCandidate( processed, toProcess ) { + const ratio = sum( take( toProcess, 4 ) ); + return ( + ( fourIsNotRecent( processed ) && ( ratio < 3.5 && toProcess.length > 5 ) ) || + ( ratio < 7 && toProcess.length === 4 ) + ); +} + +function isNotRecentShape( shape, numRecents ) { + return recents => + ! some( takeRight( recents, numRecents ), recentShape => isEqual( recentShape, shape ) ); +} + +function checkNextRatios( shape ) { + return ratios => + ratios.length >= shape.length && + every( zipWith( shape, ratios.slice( 0, shape.length ), ( f, r ) => f( r ) ) ); +} + +function isLandscape( ratio ) { + return ratio >= 1 && ratio < 2; +} + +function isPortrait( ratio ) { + return ratio < 1; +} + +function isPanoramic( ratio ) { + return ratio >= 2; +} + +// >= +function gte( n ) { + return m => m >= n; +} + +// < +function lt( n ) { + return m => m < n; +} diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/resize.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/resize.js new file mode 100644 index 0000000000000..022729c8bac72 --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/mosaic/resize.js @@ -0,0 +1,107 @@ +/** + * Internal dependencies + */ +import { GUTTER_WIDTH } from '../../constants'; + +/** + * Distribute a difference across ns so that their sum matches the target + * + * @param {Array} parts Array of numbers to fit + * @param {number} target Number that sum should match + * @return {Array} Adjusted parts + */ +function adjustFit( parts, target ) { + const diff = target - parts.reduce( ( sum, n ) => sum + n, 0 ); + const partialDiff = diff / parts.length; + return parts.map( p => p + partialDiff ); +} + +export function handleRowResize( row, width ) { + applyRowRatio( row, getRowRatio( row ), width ); +} + +function getRowRatio( row ) { + const result = getRowCols( row ) + .map( getColumnRatio ) + .reduce( + ( [ ratioA, weightedRatioA ], [ ratioB, weightedRatioB ] ) => { + return [ ratioA + ratioB, weightedRatioA + weightedRatioB ]; + }, + [ 0, 0 ] + ); + return result; +} + +export function getGalleryRows( gallery ) { + return Array.from( gallery.querySelectorAll( '.tiled-gallery__row' ) ); +} + +function getRowCols( row ) { + return Array.from( row.querySelectorAll( '.tiled-gallery__col' ) ); +} + +function getColImgs( col ) { + return Array.from( + col.querySelectorAll( '.tiled-gallery__item > img, .tiled-gallery__item > a > img' ) + ); +} + +function getColumnRatio( col ) { + const imgs = getColImgs( col ); + const imgCount = imgs.length; + const ratio = + 1 / + imgs.map( getImageRatio ).reduce( ( partialColRatio, imgRatio ) => { + return partialColRatio + 1 / imgRatio; + }, 0 ); + const result = [ ratio, ratio * imgCount || 1 ]; + return result; +} + +function getImageRatio( img ) { + const w = parseInt( img.dataset.width, 10 ); + const h = parseInt( img.dataset.height, 10 ); + const result = w && ! Number.isNaN( w ) && h && ! Number.isNaN( h ) ? w / h : 1; + return result; +} + +function applyRowRatio( row, [ ratio, weightedRatio ], width ) { + const rawHeight = + ( 1 / ratio ) * ( width - GUTTER_WIDTH * ( row.childElementCount - 1 ) - weightedRatio ); + + applyColRatio( row, { + rawHeight, + rowWidth: width - GUTTER_WIDTH * ( row.childElementCount - 1 ), + } ); +} + +function applyColRatio( row, { rawHeight, rowWidth } ) { + const cols = getRowCols( row ); + + const colWidths = cols.map( + col => ( rawHeight - GUTTER_WIDTH * ( col.childElementCount - 1 ) ) * getColumnRatio( col )[ 0 ] + ); + + const adjustedWidths = adjustFit( colWidths, rowWidth ); + + cols.forEach( ( col, i ) => { + const rawWidth = colWidths[ i ]; + const width = adjustedWidths[ i ]; + applyImgRatio( col, { + colHeight: rawHeight - GUTTER_WIDTH * ( col.childElementCount - 1 ), + width, + rawWidth, + } ); + } ); +} + +function applyImgRatio( col, { colHeight, width, rawWidth } ) { + const imgHeights = getColImgs( col ).map( img => rawWidth / getImageRatio( img ) ); + const adjustedHeights = adjustFit( imgHeights, colHeight ); + + // Set size of col children, not the element + Array.from( col.children ).forEach( ( item, i ) => { + const height = adjustedHeights[ i ]; + item.setAttribute( 'style', `height:${ height }px;width:${ width }px;` ); + } ); +} diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/row.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/row.js new file mode 100644 index 0000000000000..200a58c2e3acf --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/row.js @@ -0,0 +1,8 @@ +/** + * External dependencies + */ +import classnames from 'classnames'; + +export default function Row( { children, className } ) { + return
{ children }
; +} diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/square.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/square.js new file mode 100644 index 0000000000000..2a1ab888b1916 --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/layout/square.js @@ -0,0 +1,33 @@ +/** + * External dependencies + */ +import { chunk, drop, take } from 'lodash'; + +/** + * Internal dependencies + */ +import Row from './row'; +import Column from './column'; +import Gallery from './gallery'; +import { MAX_COLUMNS } from '../constants'; + +export default function Square( { columns, renderedImages } ) { + const columnCount = Math.min( MAX_COLUMNS, columns ); + + const remainder = renderedImages.length % columnCount; + + return ( + + { [ + ...( remainder ? [ take( renderedImages, remainder ) ] : [] ), + ...chunk( drop( renderedImages, remainder ), columnCount ), + ].map( ( imagesInRow, rowIndex ) => ( + + { imagesInRow.map( ( image, colIndex ) => ( + { image } + ) ) } + + ) ) } + + ); +} diff --git a/client/gutenberg/extensions/tiled-gallery/deprecated/v1/save.js b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/save.js new file mode 100644 index 0000000000000..65da6915ab562 --- /dev/null +++ b/client/gutenberg/extensions/tiled-gallery/deprecated/v1/save.js @@ -0,0 +1,31 @@ +/** + * Internal dependencies + */ +import Layout from './layout'; +import { getActiveStyleName } from 'gutenberg/extensions/utils'; +import { LAYOUT_STYLES } from './constants'; + +export function defaultColumnsNumber( attributes ) { + return Math.min( 3, attributes.images.length ); +} + +export default function TiledGallerySave( { attributes } ) { + const { images } = attributes; + + if ( ! images.length ) { + return null; + } + + const { align, className, columns = defaultColumnsNumber( attributes ), linkTo } = attributes; + + return ( + + ); +} diff --git a/client/gutenberg/extensions/tiled-gallery/gallery-image/save.js b/client/gutenberg/extensions/tiled-gallery/gallery-image/save.js index e617c0fb1b12d..ac57133da7229 100644 --- a/client/gutenberg/extensions/tiled-gallery/gallery-image/save.js +++ b/client/gutenberg/extensions/tiled-gallery/gallery-image/save.js @@ -9,7 +9,6 @@ import { isBlobURL } from '@wordpress/blob'; export default function GalleryImageSave( props ) { const { - 'aria-label': ariaLabel, alt, // caption, imageFilter, @@ -40,7 +39,6 @@ export default function GalleryImageSave( props ) { const img = ( { Date: Fri, 1 Mar 2019 13:22:40 +0200 Subject: [PATCH 17/29] Form block: fix typo (#31139) --- client/gutenberg/extensions/contact-form/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/gutenberg/extensions/contact-form/index.js b/client/gutenberg/extensions/contact-form/index.js index 209849e1c0b9b..159429b0f9b57 100644 --- a/client/gutenberg/extensions/contact-form/index.js +++ b/client/gutenberg/extensions/contact-form/index.js @@ -399,7 +399,7 @@ export const childBlocks = [ title: __( 'Radio' ), keywords: [ __( 'Choose' ), __( 'Select' ), __( 'Option' ) ], description: __( - 'Inpsired by radios, only one radio item can be selected at a time. Add several radio button items.' + 'Inspired by radios, only one radio item can be selected at a time. Add several radio button items.' ), icon: renderMaterialIcon( From 08a309b47df999f22151396298902c1d9ddb4951 Mon Sep 17 00:00:00 2001 From: Jefferson Rabb Date: Fri, 1 Mar 2019 09:30:05 -0500 Subject: [PATCH 18/29] Mailchimp: Placeholder Buttons (#31089) * Rework of button UI hierarchy in unconnected placeholder. * Change to Connection button styling. * Add isBorderless to Re-check button. * Revised button attributes for placeholder. * Further revisions to button styles. --- client/gutenberg/extensions/mailchimp/edit.jsx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/gutenberg/extensions/mailchimp/edit.jsx b/client/gutenberg/extensions/mailchimp/edit.jsx index 39cd2bba7f620..c39098eeb13dd 100644 --- a/client/gutenberg/extensions/mailchimp/edit.jsx +++ b/client/gutenberg/extensions/mailchimp/edit.jsx @@ -144,10 +144,13 @@ class MailchimpSubscribeEdit extends Component { 'You need to connect your Mailchimp account and choose a list in order to start collecting Email subscribers.' ) }
- { __( 'Set up Mailchimp form' ) } +
+

-
From 9850bb121120480a2c906cba31d151585724b2c8 Mon Sep 17 00:00:00 2001 From: Jefferson Rabb Date: Fri, 1 Mar 2019 09:44:38 -0500 Subject: [PATCH 19/29] Mailchimp: Form Element Spacing (#31142) * Standardized form element spacing in the editor. * Use rem for form element spacing. --- client/gutenberg/extensions/mailchimp/edit.jsx | 1 + client/gutenberg/extensions/mailchimp/editor.scss | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/client/gutenberg/extensions/mailchimp/edit.jsx b/client/gutenberg/extensions/mailchimp/edit.jsx index c39098eeb13dd..0e8654c056fda 100644 --- a/client/gutenberg/extensions/mailchimp/edit.jsx +++ b/client/gutenberg/extensions/mailchimp/edit.jsx @@ -194,6 +194,7 @@ class MailchimpSubscribeEdit extends Component {
false } placeholder={ emailPlaceholder } diff --git a/client/gutenberg/extensions/mailchimp/editor.scss b/client/gutenberg/extensions/mailchimp/editor.scss index 311fb2a1ce67d..84de75481ad0a 100644 --- a/client/gutenberg/extensions/mailchimp/editor.scss +++ b/client/gutenberg/extensions/mailchimp/editor.scss @@ -18,4 +18,12 @@ display: none; } + .wp-block-jetpack-mailchimp_text-input, .jetpack-submit-button { + margin-bottom: 1.5rem; + } + + .wp-block-button .wp-block-button__link { + margin-top: 0; + } + } From bf271700ba1152858106fc818cefcae5f2783f07 Mon Sep 17 00:00:00 2001 From: Mikael Korpela Date: Fri, 1 Mar 2019 17:49:01 +0200 Subject: [PATCH 20/29] Business hours block: use blockIcon in placeholder (#31143) --- client/gutenberg/extensions/business-hours/edit.jsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/client/gutenberg/extensions/business-hours/edit.jsx b/client/gutenberg/extensions/business-hours/edit.jsx index cfa1665ea2fb8..a0f6e30c696ae 100644 --- a/client/gutenberg/extensions/business-hours/edit.jsx +++ b/client/gutenberg/extensions/business-hours/edit.jsx @@ -1,6 +1,7 @@ /** * External dependencies */ +import { BlockIcon } from '@wordpress/editor'; import { Component } from '@wordpress/element'; import { Placeholder } from '@wordpress/components'; import apiFetch from '@wordpress/api-fetch'; @@ -75,7 +76,12 @@ class BusinessHours extends Component { } if ( ! hasFetched ) { - return ; + return ( + } + label={ __( 'Loading business hours' ) } + /> + ); } return ( From 1d98d30105242a862402c64ec8e93d0dd99af4e7 Mon Sep 17 00:00:00 2001 From: Rocco Tripaldi Date: Mon, 4 Mar 2019 08:12:05 -0500 Subject: [PATCH 21/29] Fix: business hours validation (#31122) * When saving a business hours block, don't save any data that hinges on localization. * defaultLocalization should not be translated. * After a conversation with @sirreal - we've decided on this approach: drop the save component altogether, because we use server-side rendering for the block have a and component for client side rendering, which are only rendered once we've fetched localization * Default days should remain localized. --- .../components/{day.jsx => day-edit.jsx} | 4 +- .../{day-save.jsx => day-preview.jsx} | 4 +- .../extensions/business-hours/edit.jsx | 37 +++++++++++-------- .../extensions/business-hours/index.js | 4 +- 4 files changed, 28 insertions(+), 21 deletions(-) rename client/gutenberg/extensions/business-hours/components/{day.jsx => day-edit.jsx} (98%) rename client/gutenberg/extensions/business-hours/components/{day-save.jsx => day-preview.jsx} (95%) diff --git a/client/gutenberg/extensions/business-hours/components/day.jsx b/client/gutenberg/extensions/business-hours/components/day-edit.jsx similarity index 98% rename from client/gutenberg/extensions/business-hours/components/day.jsx rename to client/gutenberg/extensions/business-hours/components/day-edit.jsx index 9245c38c84111..f0120c621f075 100644 --- a/client/gutenberg/extensions/business-hours/components/day.jsx +++ b/client/gutenberg/extensions/business-hours/components/day-edit.jsx @@ -14,7 +14,7 @@ import { __ } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; const defaultOpen = '09:00'; const defaultClose = '17:00'; -class Day extends Component { +class DayEdit extends Component { renderInterval = ( interval, intervalIndex ) => { const { day } = this.props; const { opening, closing } = interval; @@ -197,4 +197,4 @@ class Day extends Component { } } -export default Day; +export default DayEdit; diff --git a/client/gutenberg/extensions/business-hours/components/day-save.jsx b/client/gutenberg/extensions/business-hours/components/day-preview.jsx similarity index 95% rename from client/gutenberg/extensions/business-hours/components/day-save.jsx rename to client/gutenberg/extensions/business-hours/components/day-preview.jsx index 146a9dc6a8763..34cb6539dd45b 100644 --- a/client/gutenberg/extensions/business-hours/components/day-save.jsx +++ b/client/gutenberg/extensions/business-hours/components/day-preview.jsx @@ -11,7 +11,7 @@ import { sprintf } from '@wordpress/i18n'; */ import { _x } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; -class DaySave extends Component { +class DayPreview extends Component { formatTime( time ) { const { timeFormat } = this.props; const [ hours, minutes ] = time.split( ':' ); @@ -55,4 +55,4 @@ class DaySave extends Component { } } -export default DaySave; +export default DayPreview; diff --git a/client/gutenberg/extensions/business-hours/edit.jsx b/client/gutenberg/extensions/business-hours/edit.jsx index a0f6e30c696ae..a227446b2a92e 100644 --- a/client/gutenberg/extensions/business-hours/edit.jsx +++ b/client/gutenberg/extensions/business-hours/edit.jsx @@ -11,8 +11,8 @@ import { __experimentalGetSettings } from '@wordpress/date'; /** * Internal dependencies */ -import Day from 'gutenberg/extensions/business-hours/components/day'; -import DaySave from 'gutenberg/extensions/business-hours/components/day-save'; +import DayEdit from 'gutenberg/extensions/business-hours/components/day-edit'; +import DayPreview from 'gutenberg/extensions/business-hours/components/day-preview'; import { icon } from 'gutenberg/extensions/business-hours/index'; import { __ } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; @@ -53,13 +53,22 @@ class BusinessHours extends Component { } render() { - const { attributes, className, isEdit, isSelected } = this.props; + const { attributes, className, isSelected } = this.props; const { days } = attributes; const { localization, hasFetched } = this.state; const { startOfWeek } = localization; const localizedWeek = days.concat( days.slice( 0, startOfWeek ) ).slice( startOfWeek ); - if ( ! isEdit || ! isSelected ) { + if ( ! hasFetched ) { + return ( + } + label={ __( 'Loading business hours' ) } + /> + ); + } + + if ( ! isSelected ) { const settings = __experimentalGetSettings(); const { formats: { time }, @@ -68,26 +77,24 @@ class BusinessHours extends Component {
{ localizedWeek.map( ( day, key ) => { return ( - + ); } ) }
); } - if ( ! hasFetched ) { - return ( - } - label={ __( 'Loading business hours' ) } - /> - ); - } - return (
{ localizedWeek.map( ( day, key ) => { - return ; + return ( + + ); } ) }
); diff --git a/client/gutenberg/extensions/business-hours/index.js b/client/gutenberg/extensions/business-hours/index.js index 6c62347628024..3a8c31c8ee29b 100644 --- a/client/gutenberg/extensions/business-hours/index.js +++ b/client/gutenberg/extensions/business-hours/index.js @@ -96,7 +96,7 @@ export const settings = { }, }, - edit: props => , + edit: props => , - save: props => , + save: () => null, }; From db6f20e89c1b5fdc2847ee1cfbd4239308031075 Mon Sep 17 00:00:00 2001 From: Mikael Korpela Date: Mon, 4 Mar 2019 16:02:34 +0200 Subject: [PATCH 22/29] Tiled gallery block: camel case product name (#31184) --- client/gutenberg/extensions/tiled-gallery/edit.jsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/gutenberg/extensions/tiled-gallery/edit.jsx b/client/gutenberg/extensions/tiled-gallery/edit.jsx index 3e864a62897aa..7eec78e42a44e 100644 --- a/client/gutenberg/extensions/tiled-gallery/edit.jsx +++ b/client/gutenberg/extensions/tiled-gallery/edit.jsx @@ -212,7 +212,7 @@ class TiledGalleryEdit extends Component { icon={
{ icon }
} className={ className } labels={ { - title: __( 'Tiled gallery' ), + title: __( 'Tiled Gallery' ), name: __( 'images' ), } } onSelect={ this.onSelectImages } @@ -232,7 +232,7 @@ class TiledGalleryEdit extends Component { { controls } - + { layoutSupportsColumns( layoutStyle ) && images.length > 1 && ( Date: Mon, 4 Mar 2019 16:05:04 +0100 Subject: [PATCH 23/29] VideoPress: Disable re-usable block feature for video blocks (#31186) --- client/gutenberg/extensions/videopress/editor.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/gutenberg/extensions/videopress/editor.js b/client/gutenberg/extensions/videopress/editor.js index da021d8819d54..b0f742635bebe 100644 --- a/client/gutenberg/extensions/videopress/editor.js +++ b/client/gutenberg/extensions/videopress/editor.js @@ -94,6 +94,11 @@ const addVideoPressSupport = ( settings, name ) => { ], }, + supports: { + ...settings.supports, + reusable: false, + }, + edit: withVideoPressEdit( settings.edit ), save: withVideoPressSave( settings.save ), From 527a4a3a88222e0473f77577fb68e6dba73e109a Mon Sep 17 00:00:00 2001 From: Michael Turk Date: Mon, 4 Mar 2019 11:55:53 -0500 Subject: [PATCH 24/29] Change contact info icon to account box (#31190) --- client/gutenberg/extensions/contact-info/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/gutenberg/extensions/contact-info/index.js b/client/gutenberg/extensions/contact-info/index.js index d880df4e8c863..383b054dbb653 100644 --- a/client/gutenberg/extensions/contact-info/index.js +++ b/client/gutenberg/extensions/contact-info/index.js @@ -37,7 +37,7 @@ export const settings = { _x( 'address', 'block search term' ), ], icon: renderMaterialIcon( - + ), category: 'jetpack', supports: { From 556b30359028842b6802326dd64ba05726bbd90a Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 4 Mar 2019 18:50:52 +0100 Subject: [PATCH 25/29] Deselect image on filter change --- client/gutenberg/extensions/tiled-gallery/edit.jsx | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/gutenberg/extensions/tiled-gallery/edit.jsx b/client/gutenberg/extensions/tiled-gallery/edit.jsx index 7eec78e42a44e..2e6f2e47e5d52 100644 --- a/client/gutenberg/extensions/tiled-gallery/edit.jsx +++ b/client/gutenberg/extensions/tiled-gallery/edit.jsx @@ -197,7 +197,10 @@ class TiledGalleryEdit extends Component { setAttributes( { imageFilter: value } ) } + onChange={ value => { + setAttributes( { imageFilter: value } ); + this.setState( { selectedImage: null } ); + } } /> ) } From 99ea6c4aa0593858fbd1560b774405ff7f8de721 Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 4 Mar 2019 18:24:30 +0100 Subject: [PATCH 26/29] Update filter icons via https://github.com/Automattic/wp-calypso/pull/30853#issuecomment-469314612 --- .../tiled-gallery/filter-toolbar.js | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/client/gutenberg/extensions/tiled-gallery/filter-toolbar.js b/client/gutenberg/extensions/tiled-gallery/filter-toolbar.js index 1782c5e0001a2..1c8011f855ba9 100644 --- a/client/gutenberg/extensions/tiled-gallery/filter-toolbar.js +++ b/client/gutenberg/extensions/tiled-gallery/filter-toolbar.js @@ -11,10 +11,10 @@ import { __, _x } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; const availableFilters = [ { icon: ( - /* Custom icon */ + /* No filter */ - + ), title: _x( 'Original', 'image style' ), @@ -22,10 +22,10 @@ const availableFilters = [ }, { icon: ( - /* Material Black and White icon */ + /* 1 */ - - + + ), title: _x( 'Black and White', 'image style' ), @@ -33,10 +33,10 @@ const availableFilters = [ }, { icon: ( - /* Material Vintage icon */ + /* 2 */ - + ), title: _x( 'Sepia', 'image style' ), @@ -44,10 +44,10 @@ const availableFilters = [ }, { icon: ( - /* Custom icon */ + /* 3 */ - + ), title: '1977', @@ -55,10 +55,10 @@ const availableFilters = [ }, { icon: ( - /* Material Tonality icon */ + /* 4 */ - + ), title: _x( 'Clarendon', 'image style' ), @@ -66,10 +66,10 @@ const availableFilters = [ }, { icon: ( - /* Material Drama icon */ + /* 5 */ - - + + ), title: _x( 'Gingham', 'image style' ), From d1f401cf130285fdf01185c3b8898f44357fbfdf Mon Sep 17 00:00:00 2001 From: Jefferson Rabb Date: Mon, 4 Mar 2019 15:40:14 -0500 Subject: [PATCH 27/29] Slideshow: Replace Buttons With A Tags (#31175) * Replace Slideshow buttons with A tags. Hide inner text in links. Disable ESLint rule related to anchors without HREFs. * Remove text from PREV/NEXT/PAUSE buttons, to avoid block invalidation after language change. * Reposition bullets element below buttons (no visible change). * Remove localization of text for initial autoplay Pause button state. All a11y label localization will be addressed as a later block of work. * Removing unneeded CSS now that buttons have no inner content. --- .../extensions/slideshow/slideshow.js | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/client/gutenberg/extensions/slideshow/slideshow.js b/client/gutenberg/extensions/slideshow/slideshow.js index a11a799fc1727..722fbebecda4e 100644 --- a/client/gutenberg/extensions/slideshow/slideshow.js +++ b/client/gutenberg/extensions/slideshow/slideshow.js @@ -3,7 +3,6 @@ */ import ResizeObserver from 'resize-observer-polyfill'; import classnames from 'classnames'; -import { __ } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; import { Component, createRef } from '@wordpress/element'; import { isBlobURL } from '@wordpress/blob'; import { isEqual } from 'lodash'; @@ -105,6 +104,7 @@ class Slideshow extends Component { const { autoplay, className, delay, effect, images } = this.props; // Note: React omits the data attribute if the value is null, but NOT if it is false. // This is the reason for the unusual logic related to autoplay below. + /* eslint-disable jsx-a11y/anchor-is-valid */ return (
) ) } -
-
); + /* eslint-enable jsx-a11y/anchor-is-valid */ } prefersReducedMotion = () => { From 6ca73c8db95cb903dcfa9ef63f70369d4cd3af1c Mon Sep 17 00:00:00 2001 From: Jon Surrell Date: Mon, 4 Mar 2019 16:19:14 +0100 Subject: [PATCH 28/29] Fix WordAds block alignment Remove content floating by removing conflicting align{left,right,center} classes. Gutenberg styling handles left/right alignment. Apply center alignment based on data-align attributes. --- client/gutenberg/extensions/wordads/edit.js | 8 ++------ client/gutenberg/extensions/wordads/editor.scss | 8 +++----- 2 files changed, 5 insertions(+), 11 deletions(-) diff --git a/client/gutenberg/extensions/wordads/edit.js b/client/gutenberg/extensions/wordads/edit.js index 5556571071f3c..b3fcebb0a94d0 100644 --- a/client/gutenberg/extensions/wordads/edit.js +++ b/client/gutenberg/extensions/wordads/edit.js @@ -1,7 +1,6 @@ /** * External dependencies */ -import classNames from 'classnames'; import { __ } from 'gutenberg/extensions/presets/jetpack/utils/i18n'; import { BlockControls } from '@wordpress/editor'; import { Component, Fragment } from '@wordpress/element'; @@ -19,10 +18,7 @@ import './editor.scss'; class WordAdsEdit extends Component { render() { const { attributes, setAttributes } = this.props; - const { align, format } = attributes; - const classes = classNames( 'wp-block-jetpack-wordads', `jetpack-wordads-${ format }`, { - [ `align${ align }` ]: align, - } ); + const { format } = attributes; const selectedFormatObject = AD_FORMATS.filter( ( { tag } ) => tag === format )[ 0 ]; return ( @@ -33,7 +29,7 @@ class WordAdsEdit extends Component { onChange={ nextFormat => setAttributes( { format: nextFormat } ) } /> -
+
Date: Mon, 4 Mar 2019 21:59:37 +0100 Subject: [PATCH 29/29] Jetpack Blocks: update blocks for the final 7.1 release. --- client/gutenberg/extensions/presets/jetpack/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/gutenberg/extensions/presets/jetpack/package.json b/client/gutenberg/extensions/presets/jetpack/package.json index 1440e1efe5161..bec5346b8d9a1 100644 --- a/client/gutenberg/extensions/presets/jetpack/package.json +++ b/client/gutenberg/extensions/presets/jetpack/package.json @@ -1,6 +1,6 @@ { "name": "@automattic/jetpack-blocks", - "version": "13.0.0", + "version": "13.1.0", "description": "Gutenberg blocks for the Jetpack WordPress plugin", "main": "build/editor.js", "files": [